WebHU - Programozási kérdések és válaszok

Oracle SQL lekérdezés: az adatok legutóbbi módosításának megkeresése

Az adott oszlop adatainak legutóbbi módosítása óta eltelt napokat szeretném lekérni, például:

A TABLE_X tartalmazza

ID   PDATE        DATA1    DATA2
A    10-Jan-2013   5       10
A     9-Jan-2013   5       10
A     8-Jan-2013   5       11
A     7-Jan-2013   5       11
A     6-Jan-2013  14       12
A     5-Jan-2013  14       12
B    10-Jan-2013   3       15
B     9-Jan-2013   3       15
B     8-Jan-2013   9       15
B     7-Jan-2013   9       15
B     6-Jan-2013  14       15
B     5-Jan-2013  14        8

Példának okáért leegyszerűsítem a táblázatot.

Az eredmény a következő legyen:

ID  DATA1_LASTUPDATE  DATA2_LASTUPDATE
A   4                 2
B   2                 5

amely így szól: - A legutolsó frissítés 1. adata 4 napja, - A 2. adata legutóbbi frissítés 2 napja, - B adat1. utolsó frissítése 2 napja, - B adat2. utolsó frissítése 5 napja.

Az alábbi lekérdezés használata rendben van, de túl sokáig tart a befejezés, ha a valós táblára alkalmazom, amely sok rekordot tartalmaz, és hozzáadok 2 további adatoszlopot, hogy megtaláljam a legutóbbi frissítési napokat. Erre a célra a LEAD funkciót használom. Van más alternatíva a lekérdezés felgyorsítására?

with qdata1 as
(
    select ID, pdate from
    (
        select a.*, row_number() over (partition by ID order by pdate desc) rnum from
        (
            select a.*,
                   lead(data1,1,0) over (partition by ID order by pdate desc) - data1 as data1_diff
            from table_x a
        ) a
        where data1_diff <> 0
    )
    where rnum=1
),
qdata2 as
(
    select ID, pdate from
    (
        select a.*, row_number() over (partition by ID order by pdate desc) rnum from
        (
            select a.*,
                   lead(data2,1,0) over (partition by ID order by pdate desc) - data2 as data2_diff
            from table_x a
        ) a
        where data2_diff <> 0
    )
    where rnum=1
)
select a.ID,
       trunc(sysdate) - b.pdate data1_lastupdate,
       trunc(sysdate) - c.pdate data2_lastupdate,
from table_master a, qdata1 b, qdata2 c
where a.ID=b.ID(+) and a.ID=b.ID(+)
  and a.ID=c.ID(+) and a.ID=c.ID(+)

Nagyon köszönöm.

11.06.2014

Válaszok:


1

Elkerülheti a többszörös találatot az asztalon és az összekapcsolásokat, ha mindkét késleltetési (vagy lead) számítást együtt végzi:

with t as (
  select id, pdate, data1, data2,
    lag(data1) over (partition by id order by pdate) as lag_data1,
    lag(data2) over (partition by id order by pdate) as lag_data2
  from table_x
),
u as (
  select t.*,
    case when lag_data1 is null or lag_data1 != data1 then pdate end as pdate1,
    case when lag_data2 is null or lag_data2 != data2 then pdate end as pdate2
  from t
),
v as (
  select u.*,
    rank() over (partition by id order by pdate1 desc nulls last) as rn1,
    rank() over (partition by id order by pdate2 desc nulls last) as rn2
  from u
)
select v.id,
  max(trunc(sysdate) - (case when rn1 = 1 then pdate1 end))
    as data1_last_update,
  max(trunc(sysdate) - (case when rn2 = 1 then pdate2 end))
    as data2_last_update
from v
group by v.id
order by v.id;

Feltételezem, hogy adatait Jun-2014, nem Jan-2013 számára szánta; és hogy a legutóbbi módosítási dátumokat hasonlítja össze az aktuális dátummal. A 10-Jun-2014 stb. használatára igazított adatokkal ez a következőt adja:

ID DATA1_LAST_UPDATE DATA2_LAST_UPDATE
-- ----------------- -----------------
A                  4                 2 
B                  2                 5 

Az első CTE (t) megkapja a tényleges táblázatadatokat, és két extra oszlopot ad hozzá, mindegyik adatoszlophoz egyet, késleltetést használva (ami megegyezik a csökkenő dátumok szerint rendezett lead).

A második CTE (u) két dátumoszlopot ad hozzá, amelyeket csak az adatoszlopok módosításakor állítanak be (vagy amikor először állítják be őket, arra az esetre, ha soha nem változtak volna). Tehát ha egy sorban data1 ugyanaz, mint az előző sorban, akkor a pdate1 üres lesz. Az első kettőt kombinálhatja a késleltetés számításának megismétlésével, de a kicsit felosztva hagytam, hogy egy kicsit világosabb legyen.

A harmadik CTE (v) olyan rangsort rendel ezekhez a pdate oszlopokhoz, hogy a legfrissebb legyen az első helyen.

Az utolsó lekérdezés pedig kiszámítja az aktuális dátum és a legmagasabb rangú (azaz a legutóbbi) változás közötti különbséget az egyes adatoszlopok esetében.

SQL Fiddle, beleértve az összes CTE-t külön-külön, így láthatja, mit csinálnak.

11.06.2014
  • Kipróbáltam a javasolt lekérdezést, és igen, gyorsabb. Kösz. A lekérdezésem 1 percet és 8-30 másodpercet vett igénybe (nem tudom, mi okozta ezt az ingadozást), az Ön lekérdezése pedig 56 másodpercet vett igénybe. Fyi a valódi TABLE_X adat egy 2 tábla UNIÓJA, amelyben az összes rekord körülbelül 6 millió rekord. Az egyedi azonosító száma 6 ezer elem, a szűrő kritériumainak megfelelő azonosító pedig körülbelül 1250 rekord (a szűrő lekérdezést az allekérdezésbe adom hozzá). 12.06.2014
  • További szűrőt adok hozzá, és most 22 másodpercig tartott, míg az előző lekérdezésem 35 másodpercig tartott. 12.06.2014

  • 2

    A lekérdezése nem a számomra megfelelő eredményeket adta, lehet, hogy kihagytam valamit, de az alábbi lekérdezéssel is a megfelelő eredményeket kaptam (ezt ellenőrizheti: SQLFiddle bemutató):

    with ranked as (
                      select ID, 
                             data1,
                             data2,   
                             rank() over(partition by id order by pdate desc) r 
                      from table_x
                   )
    select id,
           sum(DATA1_LASTUPDATE) DATA1_LASTUPDATE,
           sum(DATA2_LASTUPDATE) DATA2_LASTUPDATE
    from (
         -- here I get when data1 was updated
             select id, 
                    count(1) DATA1_LASTUPDATE,
                    0 DATA2_LASTUPDATE
               from ranked
         start with r = 1
        CONNECT BY (PRIOR data1 = data1)
               and PRIOR r = r - 1
          group by id
        union 
      -- here I get when data2 was updated
            select id, 
                   0 DATA1_LASTUPDATE,
                   count(1) DATA0_LASTUPDATE  
               from ranked
         start with r = 1
        CONNECT BY (PRIOR data2 = data2)
               and PRIOR r = r - 1
          group by id
    )  
    group by id
    
    11.06.2014
  • Elfelejtettem elmondani, hogy a lekérdezésemben a SYSDATE-et használom a legfrissebb dátumhoz, de az adatmintához szerkesztenem kell a lekérdezést a 2013. január 10-i dátummal, nem a sysdate-val. Kipróbáltam az általad javasolt lekérdezést, de sokkal tovább tartott, mint az enyém. 12.06.2014
  • Új anyagok

    A rádiógomb ellenőrzött eseményének használata a jQueryben
    Ebben a cikkben látni fogjuk, hogyan kell dolgozni a jquery választógombbal ellenőrzött eseményeivel. A választógombok HTML gombok, amelyek segítenek kiválasztani egyetlen értéket egy csoportból...

    Körkörös függőségek megoldása terraformban adatforrásokkal – lépésről lépésre
    Mi az a körkörös függőségek Dolgozzunk egy egyszerű eseten, amikor az SQS-sor és az S3-vödör közötti körkörös függőség problémája van egy egymástól függő címkeérték miatt. provider..

    Miért érdemes elkezdeni a kódolást 2023-ban?
    01100011 01101111 01100100 01100101 — beep boop beep boop Világunk folyamatosan fejlődik a technológia körül, és naponta fejlesztenek új technológiákat a valós problémák megoldására. Amint..

    🎙 Random Noise #2  – Örökbefogadás és hit
    az analitika íratlan világának gondozása Szeretné, hogy ezek a frissítések a postaládájába kerüljenek? Iratkozzon fel itt . "Ha önvezető autókat gyártanak, akkor mi miért ne..

    A legrosszabb politika és prediktív modellek májátültetésre jelöltek számára az Egyesült Államokban
    A máj (vagy óangolul lifer) az emberi test legnehezebb belső szervére utal, amely csendesen működik a nap 24 órájában. Mit csinál a máj? 500 feladatot hajt végre a szervezet egészségének..

    5 webhely, amely 2022-ben fejleszti front-end fejlesztői készségeit
    Frontendmentor.io A tényleges projektek létrehozásával a Frontendmentor.io segítséget nyújt a front-end kódolási képességeinek fejlesztésében. A kódolást azután kezdheti meg, hogy..

    Mikor kell használni a Type-t az interfészhez képest a TypeScriptben?
    A TypeScript a JavaScript gépelt szuperkészlete, amely statikus gépelést ad a nyelvhez. Ez megkönnyíti a robusztus és karbantartható kód írását azáltal, hogy a hibákat a fordítási időben..