2017-12-07 6 views
1

In einer Tabelle, ich brauche zwei Datensätze in einem Datensatz zu kombinieren, basierend auf Spalten (in diesem Fall Spalte 1.WORK_ORDER_NUM, 2.ESN 3.PLANT 4. REMD_PART_NUM 5. REMD_PART_SERIAL). Wenn diese 5 Spalten gleich sind, muss ich die Aggregatfunktion in der anderen Spalte verwenden, um sie zu einem Datensatz zu machen [In diesem Fall sind die Spalten LLP_TRACKD_PART_IND, REMD_PART_TSN und REMD_PART_CSN].sql Feinabstimmung

Dies ist, was ich versucht habe:

SELECT decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)PLANT, 
COUNT(*) RECORD_COUNT, 
COUNT(DISTINCT OFF.REMD_PART_NUM) REMD_PART_NUM_COUNT, 
COUNT(DISTINCT OFF.REMD_PART_SERIAL) REMD_PART_SER_NUM_COUNT, 
    COUNT(DECODE(LLP_TRACKD_PART_IND,'LL',LLP_TRACKD_PART_IND,NULL)) LL_COUNT, 
COUNT(DECODE(LLP_TRACKD_PART_IND,'LR',LLP_TRACKD_PART_IND,NULL)) LR_COUNT, 
COUNT(DECODE(LLP_TRACKD_PART_IND,'TR',LLP_TRACKD_PART_IND,NULL)) TR_COUNT, 
SUM(OFF.REMD_PART_QTY) TOTAL_REMD_PART_QTY, 
    SUM(decode(LLP_TRACKD_PART_IND,null,0, 
    CASE 
     WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$') 
      THEN CAST(REMD_PART_TSN AS NUMBER) 
     ELSE 0 
    END 
)) TOTAL_TSN, 
SUM(decode(LLP_TRACKD_PART_IND,null,0, 
    CASE 
     WHEN REGEXP_LIKE(REMD_PART_CSN, '^-?\d+(\.\d+)?$') 
      THEN CAST(REMD_PART_CSN AS NUMBER) 
     ELSE 0 
    END 
)) TOTAL_CSN 
FROM (with t as (SELECT distinct PLANT, 
WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL,REMD_PART_IIN, 
LLP_TRACKD_PART_IND, 
REMD_PART_QTY,REMD_PART_TSN,REMD_PART_CSN,REMD_PART_TSO,REMD_PART_CSO 
,REMD_PART_TSC,REMD_PART_CSC,REMD_CYCLE_REMAIN   
FROM <TABLE1> 
WHERE 
REMD_PART_NUM is not null 
) 
select DISTINCT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL 
,REMD_PART_IIN 
,(select max(LLP_TRACKD_PART_IND) from t bb where aa.PLANT=bb.PLANT and 
aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM 
and aa.ESN=bb.ESN 
    and aa.REMD_PART_NUM=bb.REMD_PART_NUM 
    and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL) LLP_TRACKD_PART_IND 
,REMD_PART_QTY 
,(select max(REMD_PART_TSN) from t bb where aa.PLANT=bb.PLANT and 
aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM 
and aa.ESN=bb.ESN 
and aa.REMD_PART_NUM=bb.REMD_PART_NUM 
and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL) REMD_PART_TSN 
, 
(select max(REMD_PART_CSN) from t bb where aa.PLANT=bb.PLANT and    
aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM 
    and aa.ESN=bb.ESN 
    and aa.REMD_PART_NUM=bb.REMD_PART_NUM 
    and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL) REMD_PART_CSN 
    from t aa) OFF 
WHERE 
REMD_PART_NUM is not null 
GROUP BY decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT) 

Und es dauert etwa 8 Stunden in Anspruch nehmen. Gibt es einen anderen Weg, um es schneller abzuschließen? It took 8 hours to complete

+0

Feinabstimmung? Verwenden Sie MySQL oder Oracle? (Markieren Sie keine Produkte, die nicht beteiligt sind.) – jarlh

+0

@jarlh Es ist Oracle. –

+0

Es ist Oracle. @jarlh –

Antwort

1

Beginnen Sie mit einer besseren Formatierung der Abfrage, wird er Ihnen leicht, den Code zu verstehen und sich wiederholende Muster feststellen:

SELECT decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)PLANT, 
    COUNT(*) RECORD_COUNT, 
    COUNT(DISTINCT OFF.REMD_PART_NUM) REMD_PART_NUM_COUNT, 
    COUNT(DISTINCT OFF.REMD_PART_SERIAL) REMD_PART_SER_NUM_COUNT, 
    COUNT(DECODE(LLP_TRACKD_PART_IND,'LL',LLP_TRACKD_PART_IND,NULL)) LL_COUNT, 
    COUNT(DECODE(LLP_TRACKD_PART_IND,'LR',LLP_TRACKD_PART_IND,NULL)) LR_COUNT, 
    COUNT(DECODE(LLP_TRACKD_PART_IND,'TR',LLP_TRACKD_PART_IND,NULL)) TR_COUNT, 
    SUM(OFF.REMD_PART_QTY) TOTAL_REMD_PART_QTY, 
    SUM(decode(LLP_TRACKD_PART_IND,null,0, 
      CASE 
       WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$') 
       THEN CAST(REMD_PART_TSN AS NUMBER) 
       ELSE 0 
      END 
     )) TOTAL_TSN, 
    SUM(decode(LLP_TRACKD_PART_IND,null,0, 
      CASE 
       WHEN REGEXP_LIKE(REMD_PART_CSN, '^-?\d+(\.\d+)?$') 
       THEN CAST(REMD_PART_CSN AS NUMBER) 
       ELSE 0 
      END 
     )) TOTAL_CSN 
FROM (
    with t as ( 
     SELECT distinct PLANT, WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL,REMD_PART_IIN, 
       LLP_TRACKD_PART_IND, 
       REMD_PART_QTY,REMD_PART_TSN,REMD_PART_CSN,REMD_PART_TSO,REMD_PART_CSO 
       ,REMD_PART_TSC,REMD_PART_CSC,REMD_CYCLE_REMAIN   
     FROM <TABLE1> 
     WHERE REMD_PART_NUM is not null 
    ) 
    select DISTINCT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL 
      ,REMD_PART_IIN 
      ,( select max(LLP_TRACKD_PART_IND) 
       from t bb 
       where aa.PLANT=bb.PLANT 
        and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM 
        and aa.ESN=bb.ESN 
        and aa.REMD_PART_NUM=bb.REMD_PART_NUM 
        and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL 
      ) LLP_TRACKD_PART_IND 
      ,REMD_PART_QTY 
      ,( select max(REMD_PART_TSN) from t bb 
       where aa.PLANT=bb.PLANT 
        and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM 
        and aa.ESN=bb.ESN 
        and aa.REMD_PART_NUM=bb.REMD_PART_NUM 
        and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL 
      ) REMD_PART_TSN 
      , 
      ( select max(REMD_PART_CSN) from t bb 
       where aa.PLANT=bb.PLANT 
        and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM 
        and aa.ESN=bb.ESN 
        and aa.REMD_PART_NUM=bb.REMD_PART_NUM 
        and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL 
      ) REMD_PART_CSN 
    from t aa 
) OFF 
WHERE REMD_PART_NUM is not null 
GROUP BY decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT) 
; 

Sie werden sehen, dass die folgenden Muster 3 wird wiederholt mal (3 fast identisch Subqueries):

select max(some_field) 
from t bb 
where aa.PLANT=bb.PLANT 
    and aa.WORK_ORDER_NUM=bb.WORK_ORDER_NUM 
    and aa.ESN=bb.ESN 
    and aa.REMD_PART_NUM=bb.REMD_PART_NUM 
    and aa.REMD_PART_SERIAL=bb.REMD_PART_SERIAL 

Sie werden auch leicht sehen, dass es in dieser Abfrage 3 sehr teure Sortieroperationen gibt - eine DISTINCT in der innersten Unterabfrage, dann eine weitere DISTINCT in einer anderen Unterabfrage und schließlich GROUP BY-Operation (eine Art DISTINCT) in der obersten Abfrage.


nur auf Ihre Anfrage einen Blick kann man sortieren (DISTINCT) unter Verwendung von analytischen Funktionen auf diese Weise leicht beseitigen:

SELECT * FROM (
    SELECT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL, 
      REMD_PART_IIN, REMD_PART_QTY, 
      max(LLP_TRACKD_PART_IND) over 
       (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) 
      as LLP_TRACKD_PART_IND, 
      max(REMD_PART_TSN)  over 
       (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) 
      as REMD_PART_TSN, 
      max(REMD_PART_CSN)  over 
       (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) 
      as REMD_PART_CSN, 
      row_number() over 
       (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL, REMD_PART_IIN, REMD_PART_QTY 
        order by PLANT) as Rn 
    FROM TABLE1 
    WHERE REMD_PART_NUM is not null 
) 
WHERE rn = 1 

so dass die endgültige Abfrage migh sein:

SELECT decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT)PLANT, 
    COUNT(*) RECORD_COUNT, 
    COUNT(DISTINCT OFF.REMD_PART_NUM) REMD_PART_NUM_COUNT, 
    COUNT(DISTINCT OFF.REMD_PART_SERIAL) REMD_PART_SER_NUM_COUNT, 
    COUNT(DECODE(LLP_TRACKD_PART_IND,'LL',LLP_TRACKD_PART_IND,NULL)) LL_COUNT, 
    COUNT(DECODE(LLP_TRACKD_PART_IND,'LR',LLP_TRACKD_PART_IND,NULL)) LR_COUNT, 
    COUNT(DECODE(LLP_TRACKD_PART_IND,'TR',LLP_TRACKD_PART_IND,NULL)) TR_COUNT, 
    SUM(OFF.REMD_PART_QTY) TOTAL_REMD_PART_QTY, 
    SUM(decode(LLP_TRACKD_PART_IND,null,0, 
      CASE 
       WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$') 
       THEN CAST(REMD_PART_TSN AS NUMBER) 
       ELSE 0 
      END 
     )) TOTAL_TSN, 
    SUM(decode(LLP_TRACKD_PART_IND,null,0, 
      CASE 
       WHEN REGEXP_LIKE(REMD_PART_CSN, '^-?\d+(\.\d+)?$') 
       THEN CAST(REMD_PART_CSN AS NUMBER) 
       ELSE 0 
      END 
     )) TOTAL_CSN 
FROM (
    SELECT PLANT,WORK_ORDER_NUM,ESN,REMD_PART_NUM,REMD_PART_SERIAL,REMD_PART_IIN, REMD_PART_QTY, 
      max(LLP_TRACKD_PART_IND) over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) as LLP_TRACKD_PART_IND, 
      max(REMD_PART_TSN)  over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) as REMD_PART_TSN, 
      max(REMD_PART_CSN)  over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL) as REMD_PART_CSN, 
      row_number()    over (partition by PLANT, WORK_ORDER_NUM, ESN, REMD_PART_NUM, REMD_PART_SERIAL, REMD_PART_IIN, REMD_PART_QTY 
              order by PLANT) as Rn 
    FROM TABLE1 
    WHERE REMD_PART_NUM is not null 
) 
WHERE rn = 1 
GROUP BY decode (PLANT ,'ECL','CELMA','EDS','CELMA',PLANT) 

Ich denke, dass diese Abfrage weiter optimiert werden könnte, aber es würde einen Einblick in die Struktur der Tabellen und ein Wissen erfordern ge von geschäftlichen Anforderungen.


Es sind jedoch immer noch einige Mikrooptimierungen möglich.
Dieses Muster:

SUM(decode(LLP_TRACKD_PART_IND,null,0, 
     CASE 
      WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$') 
      THEN CAST(REMD_PART_TSN AS NUMBER) 
      ELSE 0 
     END 
    )) TOTAL_TSN, 

kann mit dieser Fassung:

coalesce( 
    SUM( 
     CASE 
      WHEN REGEXP_LIKE(REMD_PART_TSN, '^-?\d+(\.\d+)?$') 
      THEN CAST(REMD_PART_TSN AS NUMBER) 
      ELSE 0 
     END 
    ), 0 
) 

seit SUM Nullen ignoriert, dann für jeden Datensatz für NULL-Wert überprüft, ist eine Verschwendung. Für eine kleine Anzahl von Aufzeichnungen (< 1 Million) spielt es keine Rolle, aber für Hunderte von Millionen von Aufzeichnungen können Sie den Effekt der Skalierung erzielen - sagen wir 0,05 ms für die Überprüfung jedes Datensatzes multipliziert mit 10.000.000 Datensätzen kann 500 Sekunden ergeben.

Verwandte Themen