Avaleht
uus teema   vasta Tarkvara »  Programmeerimine »  Päring (vms. lahendus) ajaliste "tühimike" leidmiseks (MySQL) märgi kõik teemad loetuks
märgi mitteloetuks
vaata eelmist teemat :: vaata järgmist teemat
Hinnavaatlus :: Foorum :: Uudised :: Ärifoorumid :: HV F1 ennustusvõistlus :: Pangalink :: Telekavad :: HV toote otsing
autor
sõnum Saada viide sõbrale. Teata moderaatorile
otsing:  
warwas
HV Guru
warwas

liitunud: 06.07.2003



Autoriseeritud ID-kaardiga

sõnum 02.12.2010 14:05:38 Päring (vms. lahendus) ajaliste "tühimike" leidmiseks (MySQL) vasta tsitaadiga

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
vaata kasutaja infot saada privaatsõnum
andresv
HV kasutaja

liitunud: 06.12.2004




sõnum 03.12.2010 18:38:26 vasta tsitaadiga

Ü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:
  1. SELECT g1.l6pp FROM graafik g1 LEFT JOIN graafik g2 ON (g2.algus = g1.l6pp) WHERE g2.id IS NULL
  2.  

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:
  1. 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)
  2.  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
vaata kasutaja infot saada privaatsõnum
iFlop
Kreisi kasutaja
iFlop

liitunud: 03.05.2003



Autoriseeritud ID-kaardiga

sõnum 05.12.2010 12:37:39 vasta tsitaadiga

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
vaata kasutaja infot saada privaatsõnum
AMD
HV veteran
AMD

liitunud: 29.07.2003




sõnum 05.12.2010 13:24:08 vasta tsitaadiga

Toredalt ebaefektiivne päring. icon_razz1.gif
sql:
  1. SELECT g1.l6pp AS algus_ , (SELECT min(g3.algus) FROM Graaf g3 WHERE g3.algus > algus_) AS l6pp  FROM Graaf g1 WHERE NOT EXISTS(SELECT 1 FROM Graaf g2 WHERE g2.algus = g1.l6pp);

_________________
From now on, the forum is owned by AMD.That means that you are NO LONGER allowed to talk about, or even mention *ntel.
Kommentaarid: 335 loe/lisa Kasutajad arvavad:  :: 145 :: 3 :: 12
tagasi üles
vaata kasutaja infot saada privaatsõnum mine selle kasutaja kodulehele
andrusny
Kreisi kasutaja
andrusny

liitunud: 20.03.2006




sõnum 05.12.2010 14:05:37 vasta tsitaadiga

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
vaata kasutaja infot saada privaatsõnum mine selle kasutaja kodulehele
warwas
HV Guru
warwas

liitunud: 06.07.2003



Autoriseeritud ID-kaardiga

sõnum 05.12.2010 14:09:25 vasta tsitaadiga

andrusny, thumbs_up.gif!
Kusjuures see pole üldse paha mõte!
Kommentaarid: 243 loe/lisa Kasutajad arvavad:  :: 0 :: 3 :: 221
tagasi üles
vaata kasutaja infot saada privaatsõnum
Timukas0
HV kasutaja
Timukas0

liitunud: 20.03.2007




sõnum 05.12.2010 18:32:50 vasta tsitaadiga

Pakuks siis ühe MySQL lahenduse ka välja:
sql:
  1. SET @a = '2010-12-01 12:00:00', @l = '2010-12-31 12:00:00';
  2. SELECT TIMESTAMP(@a), min(algus) AS m FROM graafik WHERE algus >= @a AND algus < @l HAVING m != @a
  3. UNION
  4. (SELECT g1.l6pp AS algus, IFNULL( (
  5.         SELECT algus
  6.         FROM graafik
  7.         WHERE algus > g1.l6pp
  8.         AND algus < @l
  9.         ORDER BY algus
  10.         LIMIT 1
  11. ), TIMESTAMP(@l)) AS l6pp
  12. FROM graafik g1
  13. LEFT JOIN graafik g2 ON g1.l6pp = g2.algus
  14. WHERE g2.id IS NULL
  15. AND g1.algus > @a
  16. 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
vaata kasutaja infot saada privaatsõnum
kiiver
HV vaatleja

liitunud: 03.04.2003




sõnum 11.12.2010 22:55:03 vasta tsitaadiga

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:
  1. -- create table GRAAFIK (ALGUS date, LOPP date);
  2. -- insert into GRAAFIK values('01.12.2010', '03.12.2010');
  3. -- insert into GRAAFIK values('03.12.2010', '04.12.2010');
  4. -- insert into GRAAFIK values('05.12.2010', '07.12.2010');
  5. -- insert into GRAAFIK values('07.12.2010', '09.12.2010');
  6.  
  7. variable D1 varchar2;
  8. variable D2 varchar2;
  9. begin
  10.   SELECT '01.12.2010', '31.12.2010' INTO :D1, :D2 FROM DUAL;
  11. end;
  12.  
  13. SELECT LOPP AS VAHEMIK_ALGUS, NEXT_ALGUS AS VAHEMIK_LOPP FROM (
  14.   SELECT LOPP, lead(ALGUS) over (ORDER BY LOPP, ALGUS) AS NEXT_ALGUS
  15.   FROM (  SELECT ALGUS, LOPP
  16.           FROM GRAAFIK
  17.           WHERE ALGUS <= to_date(:D2) AND LOPP >= to_date(:D1)
  18.         union
  19.           SELECT to_date(:D1) ALGUS, to_date(:D1) LOPP FROM DUAL
  20.         union
  21.           SELECT to_date(:D2) ALGUS, to_date(:D2) LOPP FROM DUAL
  22.        )
  23.   ORDER BY ALGUS)
  24. WHERE NEXT_ALGUS > LOPP;
Kommentaarid: 3 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 3
tagasi üles
vaata kasutaja infot saada privaatsõnum
warwas
HV Guru
warwas

liitunud: 06.07.2003



Autoriseeritud ID-kaardiga

sõnum 13.12.2010 20:49:18 vasta tsitaadiga

Timukas0 & kiiver - tänud! beer_yum.gif
Proovin kindlasti ka neid lahendusi...
Kommentaarid: 243 loe/lisa Kasutajad arvavad:  :: 0 :: 3 :: 221
tagasi üles
vaata kasutaja infot saada privaatsõnum
nemu
HV vaatleja
nemu

liitunud: 22.01.2002



Autoriseeritud ID-kaardiga

sõnum 14.12.2010 12:38:32 vasta tsitaadiga

sql:
  1.  
  2. INSERT INTO test (algus, lopp) VALUES ('2010-12-02', '2010-12-03');
  3. INSERT INTO test (algus, lopp) VALUES ('2010-12-03', '2010-12-04');
  4. INSERT INTO test (algus, lopp) VALUES ('2010-12-05', '2010-12-07');
  5. INSERT INTO test (algus, lopp) VALUES ('2010-12-07', '2010-12-09');
  6.  
  7. SET @algus = '2010-12-01 12:00:00', @lopp = '2010-12-31 12:00:00', @viimanelopp = @algus;
  8.  
  9. SELECT vabaalgus, vabalopp
  10. FROM
  11. (
  12.   SELECT
  13.     x.algus,
  14.     x.lopp,
  15.     IF (@viimanelopp < x.algus, @viimanelopp, x.algus) AS vabaalgus,
  16.     x.algus AS vabalopp,
  17.     @viimanelopp := lopp AS viimanelopp
  18.   FROM
  19.   (
  20.     SELECT algus, lopp
  21.     FROM test
  22.     WHERE algus < @lopp AND lopp > @algus
  23.     UNION ALL
  24.     SELECT @lopp AS algus, @lopp AS lopp FROM DUAL
  25.   ) x
  26.   ORDER BY x.algus
  27. ) y
  28. WHERE y.vabaalgus < y.vabalopp;
  29.  



sql:
  1.  
  2. +---------------------+---------------------+
  3. | vabaalgus           | vabalopp            |
  4. +---------------------+---------------------+
  5. | 2010-12-01 12:00:00 | 2010-12-02 00:00:00 |
  6. | 2010-12-04 00:00:00 | 2010-12-05 00:00:00 |
  7. | 2010-12-09 00:00:00 | 2010-12-31 12:00:00 |
  8. +---------------------+---------------------+
  9.  
Kommentaarid: 12 loe/lisa Kasutajad arvavad:  :: 0 :: 0 :: 11
tagasi üles
vaata kasutaja infot saada privaatsõnum
näita postitusi alates eelmisest:   
uus teema   vasta Tarkvara »  Programmeerimine »  Päring (vms. lahendus) ajaliste "tühimike" leidmiseks (MySQL)
[vaata eelmist teemat] [vaata järgmist teemat]
 lisa lemmikuks
näita foorumit:  
 ignoreeri teemat 
sa ei või postitada uusi teemasid siia foorumisse
sa ei või vastata selle foorumi teemadele
sa ei või muuta oma postitusi selles foorumis
sa ei või kustutada oma postitusi selles foorumis
sa ei või vastata küsitlustele selles foorumis
sa ei saa lisada manuseid selles foorumis
sa võid manuseid alla laadida selles foorumis



Hinnavaatlus ei vastuta foorumis tehtud postituste eest.