ORA-01799: a column may not be outer-joined to a subquery

后端 未结 6 1746
渐次进展
渐次进展 2021-01-03 20:23

Here is my query

SELECT 
    COUNT(C.SETID)
FROM 
    MYCUSTOMER C
    LEFT OUTER JOIN MYCUSTOPTION CO 
    ON 
        (C.SETID = CO.SETID 
            AND          


        
6条回答
  •  北荒
    北荒 (楼主)
    2021-01-03 20:40

    Your question has already been answered, but someone might have a slightly different case where they need to get the latest EFFDT based on a column, instead of a fixed date. For those cases, I only found one IMPERFECT option, and one UGLY solution...

    Imperfect option:

    SELECT ...
    FROM MYTABLE N, CUST_OPT C
    WHERE  etc...
    AND C.SETID           (+) = N.SETID
    AND C.CUST_ID         (+) = N.CUST_ID
    AND NVL(C.EFFDT,TO_DATE('01011900','DDMMYYYY')) = NVL((SELECT MAX(EFFDT)
                                                           FROM CUST_OPT SC
                                                           WHERE SC.SETID = C.SETID
                                                           AND   SC.CUST_ID = C.CUST_ID
                                                           AND   SC.EFFDT <= N.ISSUE_DT)
                                                           ,TO_DATE('01011900','DDMMYYYY'))
    

    It is an imperfect option because if the CUST_OPT table has future dates, but no current (<=N.ISSUE_DT) dates, the outer join will not work and no rows will be returned. In general PeopleSoft terms (yes I saw your SETID+EFFDT there! ;-D) this wouldn't happen very often as people tend to create one 01/01/1900 EFFDT to make a first value effective since "forever", but since it's not always the case; we also have an ugly solution:

    I also found one UGLY option (but I actually recommend it, and it solves the problem, so let's call it a solution), which is this:

    SELECT n.field1, n.field2,
           CASE WHEN NVL(c.EFFDT,n.ISSUE_DT-1)<=n.ISSUE_DT THEN c.field1 ELSE NULL END,
           CASE WHEN NVL(c.EFFDT,n.ISSUE_DT-1)<=n.ISSUE_DT THEN c.field2 ELSE NULL END
    FROM MYTABLE N, CUST_OPT C
    WHERE  etc...
    AND C.SETID           (+) = N.SETID
    AND C.CUST_ID         (+) = N.CUST_ID
    AND NVL(C.EFFDT,TO_DATE('01011900','DDMMYYYY')) = NVL((SELECT MAX(EFFDT)
                                                           FROM CUST_OPT SC
                                                           WHERE SC.SETID = C.SETID
                                                           AND   SC.CUST_ID = C.CUST_ID
                                                           AND   SC.EFFDT <= N.ISSUE_DT)
                                                         ,NVL( (SELECT MIN(EFFDT)
                                                                FROM CUST_OPT SC
                                                                WHERE SC.SETID = C.SETID
                                                                AND   SC.CUST_ID = C.CUST_ID
                                                                AND   SC.EFFDT >= N.ISSUE_DT)
                                                             ,TO_DATE('01011900','DDMMYYYY')
                                                             )
                                                         )
    

    This option WILL return FUTURE rows which must be ignored! So we add the conditions on the SELECT statement that will IGNORE the returned values, if they weren't meant to be retrieved. Like I said... it's an UGLY solution, but it is a solution.

    For my ugly solution, if the rows will be processed later in an Application Engine or PL/SQL or whatever; you can, instead of having a CASE statement for each column, just add a new column that will tell you that you fetched "improper" data and ignore the fields later in your code, based on this column, like this:

    CASE WHEN NVL(c.EFFDT,n.ISSUE_DT-1)<=n.ISSUE_DT THEN 'N' ELSE 'Y' END AS IGNORE_CUST_OP_COLS
    

提交回复
热议问题