Search code examples
sqloracle-databaseexcept

Minus (except) of 2 same queries return non-empty resultset


I have a problem with the following SQL. Why on the earth minus of 2 exactly same queries would return non-empty result? I have tried "UNION ALL" instead of UNION, I have tried many other things, none of which worked. PLease advise.

    SELECT y.segment1 po_num, fad.seq_num seq, fdst.short_text st
              FROM applsys.fnd_attached_documents fad,
                   applsys.fnd_documents fd,
                   applsys.fnd_documents_short_text fdst,
                   po_headers_all y
             WHERE     1 = 1
                   AND fad.pk1_value(+) = y.po_header_id
                   AND fad.entity_name = 'PO_HEADERS'
                   AND fad.document_id = fd.document_id
                   AND fd.datatype_id = 1
                   and fad.seq_num>=100
                   AND fdst.media_id = fd.media_id
                   and y.type_lookup_code='STANDARD'
                   AND NVL(y.CANCEL_FLAG,'N')='N'
                 --  and y.segment1 in (100,1000,100,650,26268)
                --   and y.segment1=1000
            UNION 
            SELECT poh.segment1, 1, '1' --null, null
              FROM    po.po_headers_all poh
                   LEFT JOIN
                      (SELECT fad1.pk1_value
                         FROM applsys.fnd_attached_documents fad1,
                              applsys.fnd_documents fd1
                        WHERE     1 = 1
                              AND fad1.entity_name = 'PO_HEADERS'
                              AND fad1.document_id = fd1.document_id
                              and fad1.seq_num>=100
                              AND fd1.datatype_id = 1) sub1
                   ON poh.po_header_id = sub1.pk1_value
             WHERE sub1.pk1_value IS NULL 
                        and poh.type_lookup_code='STANDARD'
                        AND NVL(poh.CANCEL_FLAG,'N')='N'
                      --  and poh.segment1 in (100,1000,100,650,26268) 
                      --  and poh.segment1=1000                       
          --   and poh.segment1=650)              
          minus
   SELECT y.segment1 po_num, fad.seq_num seq, fdst.short_text st
              FROM applsys.fnd_attached_documents fad,
                   applsys.fnd_documents fd,
                   applsys.fnd_documents_short_text fdst,
                   po_headers_all y
             WHERE     1 = 1
                   AND fad.pk1_value(+) = y.po_header_id
                   AND fad.entity_name = 'PO_HEADERS'
                   AND fad.document_id = fd.document_id
                   AND fd.datatype_id = 1
                   and fad.seq_num>=100
                   AND fdst.media_id = fd.media_id
                   and y.type_lookup_code='STANDARD'
                   AND NVL(y.CANCEL_FLAG,'N')='N'
                   --and y.segment1 in (100,1000,100,650,26268)
                   --and y.segment1=1000
            UNION 
            SELECT poh.segment1, 1, '1'--null,null
              FROM    po.po_headers_all poh
                   LEFT JOIN
                      (SELECT fad1.pk1_value
                         FROM applsys.fnd_attached_documents fad1,
                              applsys.fnd_documents fd1
                        WHERE     1 = 1
                              AND fad1.entity_name = 'PO_HEADERS'
                              AND fad1.document_id = fd1.document_id
                              and fad1.seq_num>=100
                              AND fd1.datatype_id = 1) sub1
                   ON poh.po_header_id = sub1.pk1_value
             WHERE sub1.pk1_value IS NULL 
                        and poh.type_lookup_code='STANDARD'
                        AND NVL(poh.CANCEL_FLAG,'N')='N'
                      --  and poh.segment1 in (100,1000,100,650,26268)
                      --  and poh.segment1=1000
                      --   and poh.segment1=650)

Solution

  • Use parentheses. Right now, you're doing ((set1 UNION set2) MINUS set1) UNION set2 while you meant to do (set1 UNION set2) MINUS (set1 UNION set2).

    In other words, you're uniting set1 and set2, removing set1 from that and uniting set2 with that, while you probably meant to take a union of set1 and set2 and remove a union of set1 and set2 from that. UNION and MINUS have the same precedence and are processed in the order they're encountered.