» »

sql, php date between periodično/letno

sql, php date between periodično/letno

Joze_K ::

Lp,
kako bi definiral sql stavek za php, ki bi izpisal recorde za trenutni datum za polja uporaben_OD, uporaben_DO. Problem, ki ga imam je v tem, da so datumi shranjeni z letom, jaz bi pa vsako leto primerjal te datume..
torej tole..
SELECT * FROM `tbl_info` WHERE CURDATE() BETWEEN uporaben_OD AND uporaben_DO

ki bo delovalo tudi 2020, 2021 in naprej, čeprav so datumi shranjeni kot npr. 2019-11-15 (se pravi z letnico 2019)
zgornji SELECT stavek jih namreč ne bo našel v letu 2020

Hvala, J

Joze_K ::

REŠIL..
tako, da celo deluje :)

SELECT * FROM `prazniki` WHERE DATE_FORMAT("2016-12-26",'%m%d') BETWEEN DATE_FORMAT(uporaben_OD,'%m%d') AND DATE_FORMAT(uporaben_DO,'%m%d')


s pomočjo
https://stackoverflow.com/questions/456...

You can use a string comparison.

DATE_FORMAT('2017-04-01','%Y%m') return date: 201704.

so your where clause should be

"created_at DATE_FORMAT(created_at,'%Y%m') >= DATE_FORMAT($date_from,'%Y%m') and 
DATE_FORMAT(created_at,'%Y%m') <= DATE_FORMAT($date_to,'%Y%m') "


lp, J

Zgodovina sprememb…

  • spremenil: Joze_K ()

Joze_K ::

ok že odkril napako...
če datum prehaja leto... npr. 2019-12-29 / 2020-01-15
potem primerja od 1229 do 0115 in seveda ni rezultata..
tuhtajmo dalje..

MrStein ::

Narediš "if" , ki preveri, ali je uporaben_OD večji od uporaben_DO in takrat obrneš primerjavo.

(če prav razumem, imaš vrstice, ki so označeni, kateri del leta "veljajo" ?)
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

smacker ::

Če obrneš primerjavo, moraš negirat tudi rezultat. "29.dec-15.jan" obnreš v "15.jan-29.dec", torej te zanimajo tisti, ki niso v tem obrnjenem intervalu. Poleg tega moraš pazit na vključitev robnih datumov - 29.12 in 15.1.
Pomoje bi bilo lažje, da v primeru da je OD večjo od DO, primerjaš če je med OD in 31.dec ali med 1.jan in OD. Pa ne rabiš IF-a, se da z WHERE in OR pokombinirat. Netestirana koda:
SELECT * FROM `prazniki` 
WHERE (
   DATE_FORMAT(uporaben_OD,'%m%d') <= DATE_FORMAT(uporaben_DO,'%m%d') AND 
   DATE_FORMAT("2016-12-26",'%m%d') BETWEEN DATE_FORMAT(uporaben_OD,'%m%d') AND DATE_FORMAT(uporaben_DO,'%m%d')
) OR (
   DATE_FORMAT(uporaben_OD,'%m%d') > DATE_FORMAT(uporaben_DO,'%m%d') AND (
      DATE_FORMAT("2016-12-26",'%m%d') BETWEEN DATE_FORMAT(uporaben_OD,'%m%d') AND '1231' OR
      DATE_FORMAT("2016-12-26",'%m%d') BETWEEN '0101' AND DATE_FORMAT(uporaben_DO,'%m%d')
   )
)

MrStein ::

Saj "if" je bil v narekovajih. Pač da se odloča med dvema možnostima...
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

klemenSLO ::

hm, ne razumem čisto tvojega vprašanja. Valda moraš tudi leto upoštevati če primerjaš uporabno do?
Life is not measured in minutes, but in MOMENTS...

smacker ::

Jaz sem tudi večkrat bral, da sem razumel. Zanimajo ga vsi recordi, ki so bili/bodo uporabni na določen dan (npr. 6. december) v kateremkoli letu. Uporabno najbrž za izpis spominov ala 'Na današnji dan pred 50. leti se je zgodilo X'.

MrStein ::

Sicer pa naj sam pove, za kaj točno gre. Če drugo ne, s primeri.
Motiti se je človeško.
Motiti se pogosto je neumno.
Vztrajati pri zmoti je... oh, pozdravljen!

ejresnevem ::

kolikor se vidi, ti to rabiš za neke obletnice; formatiraj datume v 'mmdd' obakrat kot string in primerjaj, ordinalna vrednost datuma brez leta je ohranjena.

klemenSLO ::

Nisem prepričan če je to to ker mi fali širša zgodba ampak:
ČE razpon uporabno od-do prehaja med dvemi leti, to pomeni da s tem dobiš 2 obdobji za preverjat:
1. razpon je od @uporabnoOD do 31.12
2. razpon je od 1.1. do od @uporabnoDO

Prvo osnovne recorde katere maš za preverit prepiši v novo tabelo tako ,da v takem primeru namesto 1 zapisa dobiš 2 zapisa
potem pa primerjaj recorde iz te nove tabele
Life is not measured in minutes, but in MOMENTS...

ejresnevem ::

lepo, da prineseš vse na pladnju, vzgojno pa ni

kuall ::

če imajo vsi datumi spredaj letnico 2019 potem modificiraj curdate in mu spremeni leto v 2019, da bo where lahko uporabljal indexe in bo delalo hitro.

če so letnice različne: najbolj pametno, zarad hitrost in uporabe indexov, bi bilo naredit novo kolono, kamor bi pisal samo mesec in dan. bi zagnal enkrat query, ki bi prekopiral datume v te kolone, potem pa modificiraj izvor, da bo tako zapisoval datume, če tega ne moreš pa naredi job.

pri sqlu moraš vedno mislit na to, kako uporabljat indexe, vse se mora vrteti okoli indexov, če jih ne uporabljaš je isto, kot če bi podatke pisal v flat file.

če hitrost ni važna pa uporabi DATEPART...

kuall ::

to zagonetko z različnimi letnicami se da rešiti z if stavki.

ampak za hitrost bi jaz takole naredil:
kopiraš od in do datume v novo kolono in jih formatiraš takole:
daš samo MESEC-DAN in 0 spredaj, če sta letnici enaki, če pa nista daš drugi letnici 1 spredaj

tako imaš v tej novi koloni takle format:
01229
10115
daš index nanju
curdate formatiraš na enak način
potem samo narediš curdateFORMATTED between fromFORMATTED and toFORMATTED



testi z if stavki (oziroma OR + AND):
/*
Če je klasika: DO večji od OD potem narediš enostavno GETDATE() BETWEEN @od AND @do

Če je OD manjši od DO potem GETDATE ne sme biti med @do in @od (izključivši njiju)
*/

declare @od varchar (max) = format (convert(datetime, '2019-12-29'), 'MMdd')
declare @do varchar (max) = format (convert(datetime, '2020-01-02'), 'MMdd')
declare @nao varchar (max)

set @nao = format (convert(datetime, '2011-12-28'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)
	select 'error'
else 
	select 'ok'
	
	
set @nao = format (convert(datetime, '2011-12-29'), 'MMdd')
select @nao, @od, @do
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)
	select 'ok'
else 
	select 'error'
	

set @nao = format (convert(datetime, '2011-12-30'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)
	select 'ok'
else 
	select 'error'


set @nao = format (convert(datetime, '2011-12-31'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)
	select 'ok'
else 
	select 'error'


set @nao = format (convert(datetime, '2030-01-01'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)
	select 'ok'
else 
	select 'error'


set @nao = format (convert(datetime, '2030-01-02'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)
	select 'ok'
else 
	select 'error'
	

set @nao = format (convert(datetime, '2030-01-03'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)	
	select 'error'
else 
	select 'ok'



/*
Če je klasika: DO večji od OD potem narediš enostavno GETDATE() BETWEEN @od AND @do

Če je OD manjši od DO potem GETDATE ne sme biti med @do in @od (izključivši njiju)
*/

declare @od varchar (max) = format (convert(datetime, '2019-12-25'), 'MMdd')
declare @do varchar (max) = format (convert(datetime, '2019-12-26'), 'MMdd')
declare @nao varchar (max)

set @nao = format (convert(datetime, '2019-12-24'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)
	select 'error'
else 
	select 'ok'
	
	
set @nao = format (convert(datetime, '2019-12-25'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)		
	select 'ok'
else 
	select 'error'
	

set @nao = format (convert(datetime, '2019-12-26'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)		
	select 'ok'
else 
	select 'error'


set @nao = format (convert(datetime, '2019-12-27'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)		
	select 'error'
else 
	select 'ok'


set @nao = format (convert(datetime, '2019-10-15'), 'MMdd')
if exists (select 1 from (select 1 a) x
	where 
		(
			@od <= @do
			and @nao between @od and @do
		)
		or
		(
			@od > @do
			and not (@nao > @do and @nao < @od)
		)
	)		
	select 'error'
else 
	select 'ok'

Zgodovina sprememb…

  • spremenilo: kuall ()

jype ::

Kot se temu strokovno reče...

Jesus Fitzgerald Christ.

Popravi softver in naredi schema migration, ki datume zapiše kot tip "date" in bo vse normalno delalo. Če nimaš dostopa do kode aplikacij, ki delajo poizvedbe na bazo, naredi drugo tabelo, staro tabelo z datumi pa pretvori v view s triggerjem in update proceduro, ki pravilno pretvarja podatke. Če tudi to ne gre, povej da dobra rešitev ne obstaja, slabe pa ne želiš implementirati.

kuall ::

jype je izjavil:

Jesus Fitzgerald Christ.

Enkrat sem že pisal o lolekih, ki se radi zgražajo. Ti spadaš med njih. Curb your enthusiasm se lepo dela norca iz njih.

jype ::

Pig parker.

jernejl ::

kuall je izjavil:

če imajo vsi datumi spredaj letnico 2019 potem modificiraj curdate in mu spremeni leto v 2019, da bo where lahko uporabljal indexe in bo delalo hitro.

če so letnice različne
...pa lahko spremeni leto v leto od datum_od in potem še v leto od datum_do, pa primerja oboje. Je pa treba specifično paziti še na 29.2..

no comment ::

t-sgl (ampak ziher majo tudi druge baze osnovne funkcije za delo z datumi)


select *
from TABELA
where (dateadd(year, datediff(year, getdate(), DATUM_OD), getdate()) >= DATUM_OD)
and (dateadd(year, datediff(year, DATUM_DO, getdate()), getdate()) <= DATUM_DO)

no comment ::

Če moraš pokriti še scenarij, da DATUM_OD in DATUM_DO "pokrivata" celo leto ali pa celo več let (potem vsak datum pade znotraj takega obdobja)...

select *
from TABELA
where ((dateadd(year, datediff(year, getdate(), DATUM_OD), getdate()) >= DATUM_OD)
and (dateadd(year, datediff(year, DATUM_DO, getdate()), getdate()) <= DATUM_DO))
or (datediff(day, datum_od, datum_do) > 364)

kuall ::

jernejl je izjavil:

če so letnice različne ...pa lahko spremeni leto v leto od datum_od in potem še v leto od datum_do, pa primerja oboje. Je pa treba specifično paziti še na 29.2..

Dobra ideja, se je nisem spomnil.
Če bi bila tale stran stackoverflow bi tvoj odgovor zmagal.
Ja lahko bi dobil napako 29.2. leta X ne obstaja, zato je treba dat v try catch, ko spremenimo letnico današnjemu dnevu.

Zgodovina sprememb…

  • spremenilo: kuall ()

Joze_K ::

jap, hvala vsem.. dosti dobrih idej je padlo..
pa res sem slabo zapisal problem..

ideja je naslednja.. na praznike pri nas imam v tabeli OD/DO datume, ki povedo koliko pred tem praznikom in koliko za tem praznikom naj prikazuje vsebino vezano na ta praznik... določeni prazniki se tudi prekrivajo med sabo..

ko sem te datume OD/DO vpisal v bazo, jih seveda vpiše z letnico.. jaz pa bi rad, da vsako leto samostojno ob teh praznikih gleda OD/(DO obdobje in .. nekaj naredi

zaradi tega so mi te letnice pač napoti...
ampak sem rešil edini problem prehajanja leta (novo leto) z vpeljavo dodatnega "praznika" - silvestrovo,.. kjer OD/DO teče npr od 28.12.-31.12. potem pa novo leto teče od 01.01.-10.01. in več ni problemov prehajanja med letnicami - ter mi tako lepo pride v uporabo moja funkcija, ki pretvori datume v stringe (brez letnic) in jih primerja med sabo, torej:
SELECT * FROM `prazniki` WHERE DATE_FORMAT('" . $today . "','%m%d') BETWEEN 
DATE_FORMAT(uporaben_OD,'%m%d') AND DATE_FORMAT(uporaben_DO,'%m%d')


ampak idej ste pa natrosili kup, hvala še enkrat
J

miko22 ::

Pa še jaz pristavim lonček.
Imam select:
select * from events where aktiven=1 AND tip=7 AND lastnik=1 

Tu bi še moral preveriti dodatni pogoj, da je dan enak tistemu dnevu kjer je zapisan "dateOpravila"
Dan sicer pridobim iz baze sledeče:
select DAY(dateOpravila) from events where aktiven=1 AND tip=7 AND lastnik=1

Pol ga primerjam ali je to današnji dan z funkcijo php(date).
if($trenutniDan == $danIzBaze)
......
Je pa koda grda in odvečna. Rabim nasvet, kako lahko ta dva selecta združim v enega? To pa ne znam.

smacker ::

select * from events where aktiven=1 AND tip=7 AND lastnik=1 AND DAY(dateOpravila) = DAY(CURDATE())

miko22 ::

Hvala, preprosto in deluje. Kak se nisem sam spomnil :(

mr_chai ::

kuall, a si ti mogoče pred leti razvijal software za Boeing 747 ?


Vredno ogleda ...

TemaSporočilaOglediZadnje sporočilo
TemaSporočilaOglediZadnje sporočilo
»

[jquery mobile] datepicker

Oddelek: Izdelava spletišč
71092 (824) Kocka
»

MySQL izpis vsebine iz dveh tabel

Oddelek: Programiranje
91186 (1074) iMark
»

Wordpress multiple authors

Oddelek: Izdelava spletišč
8834 (747) poweroff
»

[SQL in PHP] Preprost PHP koledarček, ki je povezan z MySQL bazo

Oddelek: Programiranje
91920 (1682) R33D3M33R
»

[java] datumi

Oddelek: Programiranje
151774 (1647) l0g1t3ch

Več podobnih tem