2014-01-28 8 views
5

Wenn ich die folgende Abfrage ausführen, bekomme ich die Meldung wieWie behebt Ora-01427 einreihige Unterabfrage gibt mehr als eine Zeile in Auswahl zurück?

„Ora-01427 einreihige Unterabfrage mehr als eine Zeile zurückgibt“

SELECT E.I_EmpID AS EMPID, 
     E.I_EMPCODE AS EMPCODE, 
     E.I_EmpName AS EMPNAME, 
     REPLACE(TO_CHAR(A.I_REQDATE, 'DD-Mon-YYYY'), ' ', '') AS FROMDATE, 
     REPLACE(TO_CHAR(A.I_ENDDATE, 'DD-Mon-YYYY'), ' ', '') AS TODATE, 
     TO_CHAR(NOD) AS NOD, 
     DECODE(A.I_DURATION, 
       'FD', 
       'FullDay', 
       'FN', 
       'ForeNoon', 
       'AN', 
       'AfterNoon') AS DURATION, 
     L.I_LeaveType AS LEAVETYPE, 
     REPLACE(TO_CHAR((SELECT C.I_WORKDATE 
         FROM T_COMPENSATION C 
         WHERE C.I_COMPENSATEDDATE = A.I_REQDATE 
          AND C.I_EMPID = A.I_EMPID), 
         'DD-Mon-YYYY'), 
       ' ', 
       '') AS WORKDATE, 
     A.I_REASON AS REASON, 
     AP.I_REJECTREASON AS REJECTREASON 
    FROM T_LEAVEAPPLY A 
INNER JOIN T_EMPLOYEE_MS E 
    ON A.I_EMPID = E.I_EmpID 
    AND UPPER(E.I_IsActive) = 'YES' 
    AND A.I_STATUS = '1' 
INNER JOIN T_LeaveType_MS L 
    ON A.I_LEAVETYPEID = L.I_LEAVETYPEID 
    LEFT OUTER JOIN T_APPROVAL AP 
    ON A.I_REQDATE = AP.I_REQDATE 
    AND A.I_EMPID = AP.I_EMPID 
    AND AP.I_APPROVALSTATUS = '1' 
WHERE E.I_EMPID <> '22' 
ORDER BY A.I_REQDATE DESC 

, wenn ich dies ausführen, ohne ORDER BY A.I_REQDATE DESC es gibt 100 Zeilen ...

Antwort

5

Verwenden Sie die folgende Abfrage:

SELECT E.I_EmpID AS EMPID, 
     E.I_EMPCODE AS EMPCODE, 
     E.I_EmpName AS EMPNAME, 
     REPLACE(TO_CHAR(A.I_REQDATE, 'DD-Mon-YYYY'), ' ', '') AS FROMDATE, 
     REPLACE(TO_CHAR(A.I_ENDDATE, 'DD-Mon-YYYY'), ' ', '') AS TODATE, 
     TO_CHAR(NOD) AS NOD, 
     DECODE(A.I_DURATION, 
       'FD', 
       'FullDay', 
       'FN', 
       'ForeNoon', 
       'AN', 
       'AfterNoon') AS DURATION, 
     L.I_LeaveType AS LEAVETYPE, 
     REPLACE(TO_CHAR((SELECT max(C.I_WORKDATE) 
         FROM T_COMPENSATION C 
         WHERE C.I_COMPENSATEDDATE = A.I_REQDATE 
          AND C.I_EMPID = A.I_EMPID), 
         'DD-Mon-YYYY'), 
       ' ', 
       '') AS WORKDATE, 
     A.I_REASON AS REASON, 
     AP.I_REJECTREASON AS REJECTREASON 
    FROM T_LEAVEAPPLY A 
INNER JOIN T_EMPLOYEE_MS E 
    ON A.I_EMPID = E.I_EmpID 
    AND UPPER(E.I_IsActive) = 'YES' 
    AND A.I_STATUS = '1' 
INNER JOIN T_LeaveType_MS L 
    ON A.I_LEAVETYPEID = L.I_LEAVETYPEID 
    LEFT OUTER JOIN T_APPROVAL AP 
    ON A.I_REQDATE = AP.I_REQDATE 
    AND A.I_EMPID = AP.I_EMPID 
    AND AP.I_APPROVALSTATUS = '1' 
WHERE E.I_EMPID <> '22' 
ORDER BY A.I_REQDATE DESC 

Der Trick ist Erzwinge, dass die innere Abfrage nur einen Datensatz zurückgibt, indem eine Aggregatfunktion hinzugefügt wird (ich habe max() hier verwendet). Dies wird perfekt funktionieren, soweit es die Abfrage betrifft, aber ehrlich gesagt sollte OP untersuchen, warum die innere Abfrage mehrere Datensätze zurückgibt, indem sie die Daten untersucht. Sind diese multiplen Aufzeichnungen wirklich betriebswirtschaftlich relevant?

+0

schön setzen, aber ein Grund wäre schöner! –

+1

@MaheswaranRavisankar Der Trick ist, die innere Abfrage zu zwingen, nur einen Datensatz zurückzugeben, indem man eine Aggregatfunktion hinzufügt (ich habe 'max() 'hier verwendet). Dies wird perfekt funktionieren, soweit es die Abfrage betrifft, aber ehrlich gesagt sollte OP untersuchen, warum die innere Abfrage mehrere Datensätze zurückgibt, indem sie die Daten untersucht. Sind diese multiplen Aufzeichnungen wirklich betriebswirtschaftlich relevant? – hashbrown

+0

Ich sehe das Aggregat MAX(). Fein! –

2

die einzige Unterabfrage dies zu sein scheint - versuchen, eine ROWNUM Grenze für die, wo das Hinzufügen sicher sein:

(SELECT C.I_WORKDATE 
     FROM T_COMPENSATION C 
     WHERE C.I_COMPENSATEDDATE = A.I_REQDATE AND ROWNUM <= 1 
     AND C.I_EMPID = A.I_EMPID) 

Sie müssen untersuchen, warum dies nicht eindeutig ist - z. der Mitarbeiter könnte mehr als eine C.I_COMPENSATEDDATE zum gleichen Datum gehabt haben.

Aus Performance-Gründen sollten Sie auch, wenn die Suche sehen Unterabfrage in eine innere/LEFT JOIN neu angeordnet werden, dh

SELECT 
    ... 
    REPLACE(TO_CHAR(C.I_WORKDATE, 'DD-Mon-YYYY'), 
      ' ', 
      '') AS WORKDATE, 
    ... 
INNER JOIN T_EMPLOYEE_MS E 
    ... 
    LEFT OUTER JOIN T_COMPENSATION C 
      ON C.I_COMPENSATEDDATE = A.I_REQDATE 
      AND C.I_EMPID = A.I_EMPID 
    ... 
+1

'ROWNUM = 1' ?? Das wird falsch sein, da die innere Abfrage selbst keinen Datensatz abruft. – hashbrown

+1

Rownum ist eine Pseudospalte. Du kannst nicht nach einem bestimmten rownum fragen. Überprüfen Sie dies: http://www.oracle.com/technetwork/issue-archive/2006/06-sep/o56asktom-086197.html – hashbrown

+0

Ja, <=. Aber das war nur um zu überprüfen, dass dies die Unterabfrage war, die das Problem verursachte. OP's Lookup funktioniert nicht so, wie er es erwartet hat. – StuartLC

Verwandte Themen