2016-07-22 7 views
1

Arbeit ich mache diese Abfrage in Oracle 11g Datenbankhaving-Klausel nicht

 SELECT DISTINCT JOC_FIN_CLTH_DFCT_LOT.LOT_NO, 
        I.ISSUE_DATE, 
        R.PROC_DESC, 
        R.RECV_DATE, 
        M.DFCT_DATE, 
        JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 
    FROM JOC_FIN_CLTH_DFCT_LOT, 
      JOC_FIN_CLTH_DFCT_MAIN M, 
      JOC_DAILY_FABRC_RECV_FOLD R, 
      JOC_LOT_ISSUE_REG I 
    WHERE  M.FCD_MAIN_ID = JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 
      AND R.LOT_NO = JOC_FIN_CLTH_DFCT_LOT.LOT_NO 
      AND I.LOT_NO = R.LOT_NO 
      AND I.LOT_YEAR = R.LOT_YEAR 
      AND JOC_FIN_CLTH_DFCT_LOT.LOT_YEAR = R.LOT_YEAR 
      AND JOC_FIN_CLTH_DFCT_LOT.LOT_YEAR = '1213' 
      AND JOC_FIN_CLTH_DFCT_LOT.FCDL_ID IN 
        ( SELECT MIN (DFCT_LOT.FCDL_ID) 
    FROM JOC_FIN_CLTH_DFCT_LOT DFCT_LOT, JOC_FIN_CLTH_DFCT_MAIN DFT_MAIN 
    WHERE DFCT_LOT.FCD_MAIN_ID IN (DFT_MAIN.FCD_MAIN_ID) 
GROUP BY DFCT_LOT.FCD_MAIN_ID) 
ORDER BY JOC_FIN_CLTH_DFCT_LOT.FCD_MAIN_ID 

es Daten innerhalb von 2 Sekunden abrufen Nr. von rows = 5100 , aber wenn ich diese Abfrage in meiner Frontend-Anwendung dauert es zu viel mal so nach der Fehlerbehebung i Unterabfrage Ursache Problem, wenn Daten finden abrufen so diese Abfrage i

SELECT DISTINCT DFCT_LOT.LOT_NO, 
        I.ISSUE_DATE, 
        R.PROC_DESC, 
        R.RECV_DATE, 
        M.DFCT_DATE, 
        DFCT_LOT.FCD_MAIN_ID 
    FROM JOC_FIN_CLTH_DFCT_LOT DFCT_LOT, 
      JOC_FIN_CLTH_DFCT_MAIN M, 
      JOC_DAILY_FABRC_RECV_FOLD R, 
      JOC_LOT_ISSUE_REG I, 
      JOC_FIN_CLTH_DFCT_MAIN DFT_MAIN 
    WHERE  M.FCD_MAIN_ID = DFCT_LOT.FCD_MAIN_ID 
      AND R.LOT_NO = DFCT_LOT.LOT_NO 
      AND I.LOT_NO = R.LOT_NO 
      AND I.LOT_YEAR = R.LOT_YEAR 
      AND DFCT_LOT.LOT_YEAR = R.LOT_YEAR 
      AND DFCT_LOT.LOT_YEAR = '1213' 
      AND DFCT_LOT.FCD_MAIN_ID IN (DFT_MAIN.FCD_MAIN_ID) 

GROUP BY DFCT_LOT.FCDL_ID, 
      DFCT_LOT.FCD_MAIN_ID, 
      DFCT_LOT.LOT_NO, 
      I.ISSUE_DATE, 
      R.PROC_DESC, 
      R.RECV_DATE, 
      M.DFCT_DATE, 
      DFCT_LOT.FCD_MAIN_ID 
HAVING DFCT_LOT.FCDL_ID in MIN (DFCT_LOT.FCDL_ID) 
ORDER BY DFCT_LOT.FCD_MAIN_ID 

diese Form der Vereinfachung vereinfachte über Abfrage aber Anzahl der Zeilen erhöhen Anzahl der Zeilen = 5578, aber ich kenne die tatsächliche Nr. von rows = 5100 having-Klausel meiner Anfrage Blick in kindly nicht, hier zu arbeiten und leite mich

+0

'min' gibt einen Wert zurück und Sie verwenden' in' damit? –

+0

also was ich damit benutze ?? – usman

+0

Warum nicht nur '='? –

Antwort

1

In Ihrer zweiten Abfrage schließen Sie sich die Tabelle JOC_FIN_CLTH_DFCT_MAIN ein zweites Mal, einmal als M und einmal als DFCT_LOT. In der zweiten Abfrage SELECT Liste nehmen Sie die erste Spalte aus M und die letzte aus DFCT_LOT.

Aber in der ersten Abfrage sind sie beide aus der gleichen M Tabelle. Wenn Sie mehr als einen Datensatz in JOC_FIN_CLTH_DFCT_MAIN für denselben FCD_MAIN_ID haben, führt dies zu mehr Kombinationen in der zweiten Abfrage, und das erklärt, warum Sie mehr Ergebnisse damit haben.

Aber es gibt einige andere Unterschiede. In der zweiten Abfrage gruppieren Sie um viele Spalten mehr als in der ersten. Darüber hinaus macht MIN (DFCT_LOT.FCDL_ID) wirklich keinen Sinn in der zweiten Abfrage, da es bereits von gruppiert wird, so ist es genau das gleiche wie nur DFCT_LOT.FCDL_ID. Als Konsequenz ist die HAVING-Klausel nur eine einfache Tautologie, und Sie könnten es genauso gut weglassen und trotzdem die gleichen Ergebnisse erzielen.

Wenn Sie sicher sind, die erste Abfrage, die Ergebnisse erhalten Sie wollen, dann würde ich eine andere Art und Weise deuten auf eine mögliche Optimierung der es zu erreichen:

SELECT  DISTINCT 
      L.LOT_NO, 
      I.ISSUE_DATE, 
      R.PROC_DESC, 
      R.RECV_DATE, 
      L.DFCT_DATE, 
      L.FCD_MAIN_ID, 
FROM  (SELECT  L.FCD_MAIN_ID, 
         L.LOT_NO, 
         L.LOT_YEAR, 
         M.DFCT_DATE, 
         ROW_NUMBER() OVER (PARTITION BY L.FCD_MAIN_ID 
              ORDER BY L.FCDL_ID) AS RN 
      FROM  JOC_FIN_CLTH_DFCT_LOT L, 
      INNER JOIN JOC_FIN_CLTH_DFCT_MAIN M 
        ON M.FCD_MAIN_ID = L.FCD_MAIN_ID 
      ) L 
INNER JOIN JOC_DAILY_FABRC_RECV_FOLD R 
     ON R.LOT_NO = L.LOT_NO 
     AND R.LOT_YEAR = L.LOT_YEAR 
INNER JOIN JOC_LOT_ISSUE_REG I 
     ON I.LOT_NO = R.LOT_NO 
     AND I.LOT_YEAR = R.LOT_YEAR 
WHERE  L.LOT_YEAR = '1213' 
     AND L.RN = 1 
ORDER BY L.FCD_MAIN_ID 

Bitte beachte, dass ich die ANSI/ISO-Syntax verwendet haben Joins, die ich Ihnen dringend empfehlen würde. Definieren von Join-Bedingungen in der WHERE-Klausel ist etwas von den Achtzigern; mach es nicht. Abfragen werden viel besser lesbar, wenn Sie an die ANSI/ISO-Syntax gewöhnt sind.

Die vorgeschlagene Abfrage wählt alle Spalten aus, die von JOC_FIN_CLTH_DFCT_LOT und JOC_FIN_CLTH_DFCT_MAIN in der Unterabfrage benötigt werden, so dass Sie diese Tabellen nicht erneut einschließen müssen.

Der Haupttrick ist die Verwendung der ROW_NUMBER Fensterfunktion, die eine Sequenznummer gemäß der PARTITION Klausel gibt. Die äußere Abfrage filtert dann nur nach den Datensätzen, die die Nummer 1 erhalten haben. Dies sind die Datensätze, in denen der Wert FCD_MAIN_ID für eine gegebene FCDL_ID minimal ist.