Search code examples
sqloracleselect-query

Check combination of values exist in table using Select query Oracle


I have below query which is not returning expected output result. For NAME column with value='PL' it should check the data in M_LOG table with NAME and E_ID column values combination and check if this combination value exist in DIR_LOG table. If it does not exist the query should return only those combination values.

Currently the query is returning all the combination value which is already exist in M_LOG table. I think i am missing small condition somewhere is query.

Select MAX(ML.NAME), ML.E_ID,  CASE   --If the day of the month is the 1st, 2nd or 3rd then it will use the last day of the previous month otherwise it will use the last day of the current month
                WHEN EXTRACT( DAY FROM SYSDATE ) <= 3
                THEN TRUNC( SYSDATE, 'MM' ) - INTERVAL '1' DAY
                ELSE LAST_DAY( TRUNC( SYSDATE ) ) END, 1, 'M1' from DIR_LOG ML, M_LOG MD
WHERE ML.NAME != MD.NAME and ML.E_ID != MD.E_ID and
ML.NAME = 'PL' 
GROUP BY ML.E_ID

Solution

  • Query Similar to "all depts not having employees"

    A common approach to this problem is to use a correlated subquery. In simpler terms using the sample schema, scott, tables, here is an example:

        SELECT
        d.deptno
    FROM
        dept d
    WHERE
        NOT EXISTS (
            SELECT
                1
            FROM
                emp e
            WHERE
                e.deptno = d.deptno
        );
    

    as opposed to an approach like this (some correspondence to your approach):

    SELECT
        d.deptno
    FROM
        dept d
        JOIN emp e ON d.deptno != e.deptno;
    

    You would need take an approach like this:

    SELECT
        MAX(ml.name),
        ml.e_id,
        CASE   --If the day of the month is the 1st, 2nd or 3rd then it will use the last day of the previous month otherwise it will use the last day of the current month
                WHEN EXTRACT(DAY FROM SYSDATE) <= 3 THEN trunc(SYSDATE,'MM') - INTERVAL '1' DAY
                ELSE last_day(trunc(SYSDATE) )
            END,
        1,
        'M1'
    FROM
        dir_log ml
    WHERE
        1 = 1
        AND   ml.name = 'PL'
    NOT EXISTS (
        SELECT
            1
        FROM
            m_log md
        WHERE
            ml.name = md.name
            AND   ml.e_id = md.e_id
    )
    GROUP BY
        ml.e_id,
        CASE
                WHEN EXTRACT(DAY FROM SYSDATE) <= 3 THEN trunc(SYSDATE,'MM') - INTERVAL '1' DAY
                ELSE last_day(trunc(SYSDATE) )
            END,
        1,
        'M1'
        ;
    

    The group by has been modified to include all non-aggregate values in the selection.