Egy táblával összetett lekérdezés

Egy táblával összetett lekérdezés
2014-07-31T15:52:51+02:00
2014-08-01T13:22:33+02:00
2022-12-01T10:30:35+01:00
BIG W
Üdv,

Van egy táblám 4 oszloppal, ebből a 2 utolsó, és az első oszlop idegen kulcsos oszlop, az első oszlop nem egyedi:

|ID|Datumtol   |  Tabla2ID|Tabla3ID|
|1| 2006-07-26 |        1        |     1       |
|2| 2008-01-23 |        3        |     4       |
|2| 2009-06-08 |        4        |     5       |

Legyen ez az érték. Azt szeretném, hogy a select-em felvenne virtuálisan egy új oszlopot dátumként, és a lekérdezést úgy adná vissza, mintha eseményszerűen változnak Tabla2ID és a Tabla3ID értékei a megadott dátumok intervallumai alapján:
Pl.:
|ID|Datumtol | Datumig|Tabla2ID|Tabla3ID|
|1 |1990-01-01|2006-07-25|NULL |   NULL    |
|1 |2006-07-26|2050-12-31|    1    |       1       |
Stb.. A 2-es ID-nál is ugyanez.
Nem tudom, hogy ez így mennyire érthető, ebből az 1990-01-01 és a 2050-12-31 a lekérdezésben használatos "új érték" lenne.
Hogyan lehet ezt megoldani?
Mutasd a teljes hozzászólást!
Nem vagyok nagy SQL guru, lehet hogy más tud rá valami szép analitikus függvényt, de én az alap tudásommal így közelíteném meg:

SELECT id, datumtol, COALESCE((SELECT MIN(dateadd('d', -1, b.datumtol)) FROM tabla b WHERE a.id=b.id AND b.datumtol>a.datumtol), '2050-12-31') datumig, tabla2ID, tabla3ID FROM tabla a;
Ez magában még nem tartalmazza a "kezdő" sorokat, azokat még egy UNION ALL-lal lehet hozzáadni:

UNION ALL SELECT id, '1990-01-01', dateadd('d', -1, MIN(datumtol)), null, null FROM tabla GROUP BY id;
És ha az egész még rendezve is kell, hogy legyen, akkor az egész vackot egy alselectbe kell rakni, ami köré lehet egy ORDER BY. Aztán hogy a query optimizer ebből csinál-e valami emberi tervet, az kétesélyes: vagy igen, vagy nem 

(Ja és SQL Serverhez nincs hozzáférésem, a szintaxis Gugli barátomnak köszönhető és lehet nem jó.)

Elég gyakori problémának tűnik, én is kíváncsi vagyok a "szép" megoldására.

szerk: TOP 1 és ORDER BY kombó helyett talán jobb a MIN az alselectben...
Mutasd a teljes hozzászólást!

  • Nem éppen erre van szükségem. Ez egy Join-os lekérdezés lenne. A null-t nem a lekérdezésben kell megadni, hanem a lekérdezés adja vissza, amennyiben az adott intervallumon kívül esik a táblában szereplő adat. Tehát teszem azt, adott sornak a dátuma: 2006-07-26, és egy olyan lekérdezést csinálok, amiben felveszek egy új dátum oszlopot (dátumtól oszlop mellé kerül az új oszlop, a dátumig), és lekérdezéssel megvizsgálom, hogy a két dátum intervallumába beleesik a 2006-07-26 dátum, ami a táblában szerepel, ha nem a Tabla2ID, Tabla3ID értéke null, egyébként egy értéket mutat ki.:
    Tehát tábla:
    |ID|Datumtol   |  Tabla2ID|Tabla3ID|
    |1| 2006-07-26 |        1        |     1       |
    |2| 2008-01-23 |        3        |     4       |
    |2| 2009-06-08 |        4        |     5       |
    A lekérdezésnek ezt kell visszaadnia pl.:
    |ID|Datumtol | Datumig           |Tabla2ID| Tabla3ID |
    |1 |1990-01-01|2006-07-25|NULL |   NULL    |
    |1 |2006-07-26|2050-12-31|    1    |       1       |
    Mutasd a teljes hozzászólást!
  • lehet hogy más tud rá valami szép analitikus függvényt

    Úgy néz ki, tényleg van rá szép analitikus függvény, a LEAD (vagy a testvérkéje, a LAG).

    Ez alapján a lekérdezés első felét elvileg így át lehet írni:

    SELECT id, datumtol, LEAD(dateadd('d', -1, datumtol), 1, '2050-12-31') OVER (PARTITION BY id ORDER BY datumtol) datumig, tabla2ID, tabla3ID FROM tabla;
    A második felét a UNION ALL-lal így se lehet megúszni, ha jól értem.
    Mutasd a teljes hozzászólást!
  • OK, most már tényleg nem értem. Le tudnád írni részletesebben a lekérdezés eredményét?

    A példádban megmutatod, mi lesz az 1-es ID-jű sorokból, de akkor mutasd már meg azt is, hogy a 2-es ID-jű sorokból mit kell visszaadnia a lekérdezésnek.
    Mutasd a teljes hozzászólást!
  • Ezek remek függvények, ám csak a 2012-es MsSQL-től érhetők el.
    LEAD és LAG - 2012-től


    Big W:

    Tehát teszem azt, adott sornak a dátuma: 2006-07-26, és egy olyan lekérdezést csinálok, amiben felveszek egy új dátum oszlopot (dátumtól oszlop mellé kerül az új oszlop, a dátumig), és lekérdezéssel megvizsgálom, hogy a két dátum intervallumába beleesik a 2006-07-26 dátum

    Bocsi, de ez nékem még picit homályos..
    Leírnád az általad elképzelt select-et?
    Mutasd a teljes hozzászólást!
  • Csaboka2:
    Ezek remek függvények, ám csak a 2012-es MsSQL-től érhetők el.
    LEAD és LAG - 2012-től


    Big W:

    Tehát teszem azt, adott sornak a dátuma: 2006-07-26, és egy olyan lekérdezést csinálok, amiben felveszek egy új dátum oszlopot (dátumtól oszlop mellé kerül az új oszlop, a dátumig), és lekérdezéssel megvizsgálom, hogy a két dátum intervallumába beleesik a 2006-07-26 dátum

    Bocsi, de ez nékem még picit homályos..
    Leírnád az általad elképzelt select-et?
    Mutasd a teljes hozzászólást!
  • Tehát egy eseményszerű táblát kell, hogy visszaadjon.
    Értéke:
    |ID|Datumtol   |  Tabla2ID|Tabla3ID|
    |1| 2006-07-26 |        1        |     1       |
    |2| 2008-01-23 |        3        |     4       |
    |2| 2009-06-08 |        4        |     5       |
    A lekérdezés eredménye kell legyen ez:
    |ID|Datumtol | Datumig     |Tabla2ID| Tabla3ID       |
    |1 |1990-01-01|2006-07-25|NULL      |         NULL     |
    |1 |2006-07-26|2050-12-31|    1         |            1        |
    |2 |1990-01-01|2008-01-22|NULL      |         NULL     |
    |2 |2008-01-23|2009-06-07|   3          |             4        |
    |2 |2009-06-08|2050-12-31|   4          |             5        |

    A lényeg, hogy a lekérdezésnél a Datumtol-Datumig oszlop intervallumként szerepel, ettől a két oszloptól függ, hogy mit ad vissza a Tabla2ID, és a Tabla3ID oszlopba.
    Mutasd a teljes hozzászólást!
  • Bocsi, a dadogásért (dupli-ért), de perceken át csak ez jött:


    504 Gateway Time-out
    Mutasd a teljes hozzászólást!
  • Nálam is.
    Mutasd a teljes hozzászólást!
  • Melyik SQL-t használod?
    Egyébként szvsz az SQL 2005-től már mindezt remekül megvalósíthatod egy tárolt eljárással..
    Mutasd a teljes hozzászólást!
  • Legutóbbi tárolt eljárásos ajánlásod után azt használom. 2008-as verziót egyébként.
    Mutasd a teljes hozzászólást!
  • Bocsi, de hiányolom a PRIMARY KEY-t a tábládból.
    Érdemes lenne beépíteni, sokat könnyítene a feldolgozásban.
    Persze tárolt eljárásban ezt is pótolhatod, kreálsz egy memtable-t abban felveszel egy primary key tip. oszlopot s másolod az eredeti táblád.
    Létrehozol egy eredmény táblát s soronként pakolgatod a min-max feltételekkel kreált adatokat.
    Mutasd a teljes hozzászólást!
  • Bocs, figyelmetlenségből nem mondtam. Az első két oszlop entity key oszlop.
    Mutasd a teljes hozzászólást!
  • Ami lekérdezést én írtam, az szerintem ezt kéne, hogy visszaadja. Találtál valami gondot vele?
    Mutasd a teljes hozzászólást!
  • Szvsz semmi köze ahhoz, amit én szeretnék megjeleníteni. Mint mondtam, ezt Join-nal jobb megoldani, és nem kell a két utolsó oszlop tábláját beírni a FROM záradékba.
    Mutasd a teljes hozzászólást!
  • Mint mondtam, ezt Join-nal jobb megoldani

    Itt is van join, csak implicit módon alselectben.

    és nem kell a két utolsó oszlop tábláját beírni a FROM záradékba.

    Hol láttál ilyet az én kódomban? Egy tábla van mindegyik FROM záradékban, nem mondtad meg a táblád nevét, úgyhogy "tabla"-nak neveztem el.
    Mutasd a teljes hozzászólást!
  • Bocs, összefolytak a betűk.:)) Köszi, próbálkozom.
    Mutasd a teljes hozzászólást!
  • A lekérdezésed eredménye:
    id datumtol datumig tabla2ID tabla3ID
    1 2006-07-26 2050-12-31 1 1
    2 2008-01-23 2009-06-07 3 4
    2 2009-06-08 2050-12-31 4 5
    1 1990-01-01 2006-07-25 NULL NULL
    2 1990-01-01 2008-01-22 NULL NULL

    ha rendezem (ID,Tabla2ID):

    ID Datumtol datumig Tabla2ID Tabla3ID
    1 1990-01-01 2006-07-25 NULL NULL
    1 2006-07-26 2050-12-31 1 1
    2 1990-01-01 2008-01-22 NULL NULL
    2 2008-01-23 2009-06-07 3 4
    2 2009-06-08 2050-12-31 4 5

    BIG W:
    Bocsi, de végül is, ezt vártad, nem?

    A lekérdezés eredménye kell legyen ez:

    |ID|Datumtol | Datumig     |Tabla2ID| Tabla3ID       |
    |1 |1990-01-01|2006-07-25|NULL      |         NULL     |
    |1 |2006-07-26|2050-12-31|    1         |            1        |
    |2 |1990-01-01|2008-01-22|NULL      |         NULL     |
    |2 |2008-01-23|2009-06-07|   3          |             4        |
    |2 |2009-06-08|2050-12-31|   4          |             5        |

    Pici hiba a lekérdezésben, de módosítva('d' helyett d):
    SELECT ID, Datumtol, COALESCE
    ((SELECT MIN(DATEADD(d, - 1, Datumtol)) AS Expr1
    FROM Table_1 AS b
    WHERE (a.ID = ID) AND (Datumtol > a.Datumtol)), '2050-12-31') AS datumig, Tabla2ID, Tabla3ID
    FROM Table_1 AS a
    UNION ALL
    SELECT ID, '1990-01-01' AS Expr1, DATEADD(d, - 1, MIN(Datumtol)) AS Expr2, NULL AS Expr3, NULL AS Expr4
    FROM Table_1
    GROUP BY ID
    ORDER BY ID,Tabla2ID
    Mutasd a teljes hozzászólást!
  • Igen, ezt... Csak ez túl bonyolult...
    Mutasd a teljes hozzászólást!
  • Csak ez túl bonyolult.

    Ha feledted tán említeni, hogy esetleg más oszlopok is vannak/lennének a kreálandó listában..

    Bocsi, de attól tartok, hogy e topikod le kéne zárnod, mert a nyitóbeli felvetésedre Csaboka2 szvsz kielégítő megoldást nyújtott.
    Persze, ha még hiányérzeted van a témával kapcsolatban, akkor nyithatnál néki egy új topikot.
    (de mindez csak az én gondolatom, tiéd a döntés joga).
    Mutasd a teljes hozzászólást!
  • Nincs más oszlop. ez az összes.
    Mutasd a teljes hozzászólást!
  • Mit jelent, hogy túl bonyolult? Mikor lenne csak elfogadható mértékben bonyolult?

    Én saját kútfőből nem nagyon fogom tudni egyszerűsíteni...
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd