Hinnavaatlus
:: Foorum
:: Uudised
:: Ärifoorumid
:: HV F1 ennustusvõistlus
:: Pangalink
:: Telekavad
:: HV toote otsing
|
|
autor |
sõnum |
|
warwas
HV Guru
liitunud: 06.07.2003
|
02.12.2010 14:05:38
Päring (vms. lahendus) ajaliste "tühimike" leidmiseks (MySQL) |
|
|
Oletame, et meil on tabel, kus on sees nö. "graafik". A'la midagi sellist:
+----+---------------------+---------------------+
| id | algus | l6pp |
+----+---------------------+---------------------+
| 1 | 01-12-2010 12:00:00 | 03-12-2010 12:00:00 |
+----+---------------------+---------------------+
| 2 | 03-12-2010 12:00:00 | 04-12-2010 12:00:00 |
+----+---------------------+---------------------+
| 3 | 05-12-2010 12:00:00 | 07-12-2010 12:00:00 |
+----+---------------------+---------------------+
| 4 | 07-12-2010 12:00:00 | 09-12-2010 12:00:00 |
+----+---------------------+---------------------+ |
Mul oleks vaja mingit päringut (vms. mõistlikku lahendust) kuidas saada kätte ajavahemikud, millede kohta mul baasis kirjeid ei ole. Võibolla sai natuke segane küsimus, aga teeks siis ühe näite veel:
Kui ma teeks sellele üleval toodud näite pihta päringu tingimusega "WHERE algus > '01-12-2010 00:00:00' AND l6pp < '31-12-2010 23:59:59'", siis ma tahaks saada vastuseks kahte rida:
+---------------------+---------------------+
| 04-12-2010 12:00:00 | 05-12-2010 12:00:00 |
+---------------------+---------------------+
| 09-12-2010 12:00:00 | 31-12-2010 12:00:00 |
+---------------------+---------------------+ |
|
|
Kommentaarid: 243 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
3 :: |
221 |
|
tagasi üles |
|
|
andresv
HV kasutaja
liitunud: 06.12.2004
|
03.12.2010 18:38:26
|
|
|
Üldiselt ei saa päring tagastada seda mida ei ole.
Ehk väga raske on märgata asju mida ei ole.
Ehk siis sul peab olema mingid defineeritud ajavahemikud, kust sa siis graafiku maha lahutad
kui sul järgmine ajavahemik algab alati samal ajal mil eelmine lõppes siis saaks teha ka päringu ala
sql:
|
SELECT g1.l6pp FROM graafik g1 LEFT JOIN graafik g2 ON (g2.algus = g1.l6pp) WHERE g2.id IS NULL
|
siis saad kõik lõpuajad millele ei järgne uut sündmust
joinides veel korra seda tabelit saad ka algused millele ei eelne midagi
sql:
|
SELECT g1.l6pp, g1.l6pp FROM graafik g1 LEFT JOIN graafik g2 ON (g2.algus = g1.l6pp) LEFT JOIN graafik g3 ON (g3.l6pp = g1.algus) WHERE g2.id IS NULL OR g3.id IS NULL
|
Aga see päring ei anna vist enam õiget tulemust
|
|
Kommentaarid: 5 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
0 :: |
5 |
|
tagasi üles |
|
|
iFlop
Kreisi kasutaja
liitunud: 03.05.2003
|
05.12.2010 12:37:39
|
|
|
Neid tühimike oleks vast mõnes programeerimiskeeles lihtsam leida. Kui nüüd ikka väga vaja, siis ehk saaks selle ka MySQL päringusse toppida, aga ei usu, et see väga kena lahendus oleks..
|
|
Kommentaarid: 66 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
0 :: |
65 |
|
tagasi üles |
|
|
AMD
HV veteran
liitunud: 29.07.2003
|
|
Kommentaarid: 335 loe/lisa |
Kasutajad arvavad: |
|
:: |
145 :: |
3 :: |
12 |
|
tagasi üles |
|
|
andrusny
Kreisi kasutaja
liitunud: 20.03.2006
|
05.12.2010 14:05:37
|
|
|
tsitaat: |
Neid tühimike oleks vast mõnes programeerimiskeeles lihtsam leida |
Pakuks välja teed ühe täis päringu tabelile
SELECT * FROM tabelnimi
ja sis lihtsalt while loop käigus eraldad need, mille lõpp aeg ja järgmise algus aeg ei kattu.
_________________
|
|
Kommentaarid: 7 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
0 :: |
7 |
|
tagasi üles |
|
|
warwas
HV Guru
liitunud: 06.07.2003
|
05.12.2010 14:09:25
|
|
|
andrusny, !
Kusjuures see pole üldse paha mõte!
|
|
Kommentaarid: 243 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
3 :: |
221 |
|
tagasi üles |
|
|
Timukas0
HV kasutaja
liitunud: 20.03.2007
|
05.12.2010 18:32:50
|
|
|
Pakuks siis ühe MySQL lahenduse ka välja:
sql:
|
SET @a = '2010-12-01 12:00:00', @l = '2010-12-31 12:00:00'; SELECT TIMESTAMP(@a), min(algus) AS m FROM graafik WHERE algus >= @a AND algus < @l HAVING m != @a UNION (SELECT g1.l6pp AS algus, IFNULL( ( SELECT algus FROM graafik WHERE algus > g1.l6pp AND algus < @l ORDER BY algus LIMIT 1 ), TIMESTAMP(@l)) AS l6pp FROM graafik g1 LEFT JOIN graafik g2 ON g1.l6pp = g2.algus WHERE g2.id IS NULL AND g1.algus > @a AND g1.l6pp <= @l);
|
Muutujad (@a ja @l) võid programmeerimiskeeles ka ära asendada.
|
|
Kommentaarid: 3 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
0 :: |
3 |
|
tagasi üles |
|
|
kiiver
HV vaatleja
liitunud: 03.04.2003
|
11.12.2010 22:55:03
|
|
|
Pakun ka hilinenult ühe lahenduse. Kui "graafik" tabel on juhtumisi väga suur siis võib parema perf. saamiseks abi olla analüütilistest funktsioonidest (näiteks LEAD, LAG). Antud päringus saab ära kaotada "graafik" joinimise iseendaga ja seega vaadatakse tabeli read läbi ainult üks kord.
Kuna pole MySQL-ga palju tegelenud, siis üks Oracle variant. Päringu osa peaks töötama samasugusena MySQL-s, eelnev väärtustamine on aga vist erineva süntaksiga.
sql:
|
-- create table GRAAFIK (ALGUS date, LOPP date); -- insert into GRAAFIK values('01.12.2010', '03.12.2010'); -- insert into GRAAFIK values('03.12.2010', '04.12.2010'); -- insert into GRAAFIK values('05.12.2010', '07.12.2010'); -- insert into GRAAFIK values('07.12.2010', '09.12.2010'); variable D1 varchar2; variable D2 varchar2; begin SELECT '01.12.2010', '31.12.2010' INTO :D1, :D2 FROM DUAL; end; SELECT LOPP AS VAHEMIK_ALGUS, NEXT_ALGUS AS VAHEMIK_LOPP FROM ( SELECT LOPP, lead(ALGUS) over (ORDER BY LOPP, ALGUS) AS NEXT_ALGUS FROM ( SELECT ALGUS, LOPP FROM GRAAFIK WHERE ALGUS <= to_date(:D2) AND LOPP >= to_date(:D1) union SELECT to_date(:D1) ALGUS, to_date(:D1) LOPP FROM DUAL union SELECT to_date(:D2) ALGUS, to_date(:D2) LOPP FROM DUAL ) ORDER BY ALGUS) WHERE NEXT_ALGUS > LOPP;
|
|
|
Kommentaarid: 3 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
0 :: |
3 |
|
tagasi üles |
|
|
warwas
HV Guru
liitunud: 06.07.2003
|
13.12.2010 20:49:18
|
|
|
Timukas0 & kiiver - tänud!
Proovin kindlasti ka neid lahendusi...
|
|
Kommentaarid: 243 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
3 :: |
221 |
|
tagasi üles |
|
|
nemu
HV vaatleja
liitunud: 22.01.2002
|
14.12.2010 12:38:32
|
|
|
sql:
|
INSERT INTO test (algus, lopp) VALUES ('2010-12-02', '2010-12-03'); INSERT INTO test (algus, lopp) VALUES ('2010-12-03', '2010-12-04'); INSERT INTO test (algus, lopp) VALUES ('2010-12-05', '2010-12-07'); INSERT INTO test (algus, lopp) VALUES ('2010-12-07', '2010-12-09'); SET @algus = '2010-12-01 12:00:00', @lopp = '2010-12-31 12:00:00', @viimanelopp = @algus; SELECT vabaalgus, vabalopp FROM ( SELECT x.algus, x.lopp, IF (@viimanelopp < x.algus, @viimanelopp, x.algus) AS vabaalgus, x.algus AS vabalopp, @viimanelopp := lopp AS viimanelopp FROM ( SELECT algus, lopp FROM test WHERE algus < @lopp AND lopp > @algus UNION ALL SELECT @lopp AS algus, @lopp AS lopp FROM DUAL ) x ORDER BY x.algus ) y WHERE y.vabaalgus < y.vabalopp;
|
sql:
|
+---------------------+---------------------+ | vabaalgus | vabalopp | +---------------------+---------------------+ | 2010-12-01 12:00:00 | 2010-12-02 00:00:00 | | 2010-12-04 00:00:00 | 2010-12-05 00:00:00 | | 2010-12-09 00:00:00 | 2010-12-31 12:00:00 | +---------------------+---------------------+
|
|
|
Kommentaarid: 12 loe/lisa |
Kasutajad arvavad: |
|
:: |
0 :: |
0 :: |
11 |
|
tagasi üles |
|
|
|