sql >> Database teknologi >  >> RDS >> Oracle

Implementering af Type 2 SCD i Oracle

Her er en tilgang til at gruppere fortløbende poster med det samme niveau, mens ændringer registreres.

Ideen er selv at slutte sig til bordet og relatere hver post til den næste post, der har et andet niveau. Dette gøres ved hjælp af en NOT EXISTS betingelse med en korreleret underforespørgsel.

LEFT JOIN er nødvendig for at undgå at bortfiltrere den sidste post (der ejer det nuværende niveau), som endnu ikke har en næste post :til denne post bruger vi COALESCE() for at indstille en standardslutdato.

SELECT c1.day day_from, COALESCE(c2.day, TO_DATE('2199-12-31', 'yyyy-mm-dd')) day_to, c1.Vendor_ID, c1.Customer_ID, c1.rank FROM customer_records c1 LEFT JOIN customer_records c2 ON c2.Vendor_ID = c1.Vendor_ID AND c2.Customer_ID = c1.Customer_ID AND c2.rank <> c1.rank AND c2.DAY > c1.DAY AND NOT EXISTS ( SELECT 1 FROM customer_records c3 WHERE c3.Vendor_ID = c1.Vendor_ID AND c3.Customer_ID = c1.Customer_ID AND c3.rank <> c1.rank AND c3.DAY > c1.DAY AND c3.DAY < c2.DAY )

Dette returnerer :

DAY_FROM | DAY_TO | Vendor_ID | Customer_ID | rank :-------- | :-------- | ------------------: | ----------: | -----------------: 24-SEP-14 | 22-OCT-14 | 71047795 | 476095 | 3103 01-OCT-14 | 22-OCT-14 | 71047795 | 476095 | 3103 08-OCT-14 | 22-OCT-14 | 71047795 | 476095 | 3103 15-OCT-14 | 22-OCT-14 | 71047795 | 476095 | 3103 22-OCT-14 | 12-NOV-15 | 71047795 | 476095 | 3102 29-OCT-14 | 12-NOV-15 | 71047795 | 476095 | 3102 05-NOV-15 | 12-NOV-15 | 71047795 | 476095 | 3102 12-NOV-15 | 31-DEC-99 | 71047795 | 476095 | 3103

Nu kan vi gruppere rekorden efter niveau og slutdato for at generere de forventede resultater. ROW_NUMBER() kan give dig versionsnummeret. Det er også nemt at kontrollere, hvilken post der er den aktuelle, som forklaret ovenfor.

SELECT 
    ROW_NUMBER() OVER(ORDER BY c2.day) version,
    DECODE(c2.day, NULL, 'Y') current_flag,
    MIN(c1.day) day_from,
    COALESCE(c2.day, TO_DATE('2199-12-31', 'yyyy-mm-dd')) day_to,
    c1.Vendor_ID,
    c1.Customer_ID, 
    c1.rank
FROM customer_records c1
LEFT JOIN customer_records c2 
    ON  c2.Vendor_ID = c1.Vendor_ID
    AND c2.Customer_ID         = c1.Customer_ID
    AND c2.rank <> c1.rank
    AND c2.DAY                 > c1.DAY
    AND NOT EXISTS (
        SELECT 1
        FROM customer_records c3
        WHERE
                c3.Vendor_Id = c1.Vendor_Id
            AND c3.Customer_ID         = c1.Customer_ID
            AND c3.rank <> c1.rank
            AND c3.DAY                 > c1.DAY
            AND c3.DAY                 < c2.DAY
    )
GROUP BY
    c1.Vendor_Id, 
    c1.Customer_ID, 
    c1.rank, 
    c2.day
ORDER BY
    day_from
 

Resultater:

VERSION | CURRENT_FLAG | DAY_FROM | DAY_TO | Leverandør_ID | Customer_ID | rang------:| :------------ | :-------- | :-------- | ------------------:| ----------:| ------------------:1 | N | 24-SEP-14 | 22-OKT-14 | 71047795 | 476095 | 3103 2 | N | 22-OKT-14 | 12-NOV-15 | 71047795 | 476095 | 3102 3 | Y | 12-NOV-15 | 31-DEC-99 | 71047795 | 476095 | 3103

I Oracle kan du omdanne et hvilket som helst udvalg til en fletteforespørgsel ved hjælp af FLETS-syntaksen . Du kan matche på alle forventede kolonner current_flag og day_to , og opdatere disse, hvis der allerede findes en post; ellers skal du bare indsætte en ny.

MERGE INTO dimensions dim
USING (
   -- above query goes here --
) cust 
    ON  dim.DAY_FROM            = cust.DAY_FROM
    AND dim.vendor_id = cust.vendor_id
    AND dim.Customer_ID         = cust.Customer_ID
    AND dim.rank  = cust.rank
WHEN MATCHED THEN UPDATE SET 
    dim.DAY_TO = cust.DAY_TO,
    dim.CURRENT_FLAG = cust.CURRENT_FLAG
WHEN NOT MATCHED THEN 
    INSERT (
        dim.DAY_FROM, 
        dim.VERSION, 
        dim.CURRENT_FLAG, 
        dim.DAY_FROM, 
        dim.DAY_TO, 
        dim.vendor_id, 
        dim.customer_id, 
        dim.rank
    ) VALUES (
        cust.DAY_FROM, 
        cust.VERSION, 
        cust.CURRENT_FLAG, 
        cust.DAY_FROM, 
        cust.DAY_TO, 
        cust.vendor_id, 
        cust.Customer_ID, 
        cust.rank
    )
 


  1. nær synatx-fejl (kode 1) indsæt Android SQLite

  2. Datarammeskrivning til Postgresql dårlig ydeevne

  3. MySQL Grant til mere end én database

  4. kommunikere MATLAB SQL Server