Home > Mobile >  Want subquery to return non-Null values
Want subquery to return non-Null values

Time:11-20

I have three tables I am using in a query; AP_INVOICES_INTERFACE , AP_INVOICE_LINES_INTERFACE , and PO_HEADERS_ALL as a subquery.

The AP_INVOICE_LINES_INTERFACE table is joined to PO_HEADERS_ALL only on the PO_NUMBER from AP_INVOICE_LINES_INTERFACE to the SEGMENT1 in PO_HEADERS_ALL. I want to populate the column 'REQ_BU_ID2' with the REQ_BU_ID value based on SEGMENT1 equaling LN.PO_NUMBER where it is not NULL.

SELECT HDR.INVOICE_ID  , HDR.PO_NUMBER , LN.PO_NUMBER LN_PO_NUMBER

, (SELECT PO2.REQ_BU_ID
    FROM PO_HEADERS_ALL PO2
    WHERE PO2.SEGMENT1 = LN.PO_NUMBER
       AND PO2.REQ_BU_ID IS NOT NULL
       AND LN.PO_NUMBER IS NOT NULL
       --AND HDR.PO_NUMBER IS NOT NULL
       AND rownum = 1    ) REQ_BU_ID2

FROM AP_INVOICES_INTERFACE HDR
INNER JOIN AP_INVOICE_LINES_INTERFACE LN ON LN.INVOICE_ID = HDR.INVOICE_ID
AND HDR.INVOICE_ID = 300000136747640

I want to populate the REQ_BU_ID2 (non-null) value for rows even when the LN.PO_NUMBER is NULL so I thought by using the AND LN.PO_NUMBER IS NOT NULL condition in the Subquery would then only return the non-null value, however as you can see it is still returning Null as well in the results:

Current Results from above query:

enter image description here

Desired Results: enter image description here

Edit:

INVOICE_ID        REQ_BU_ID2        PO_NUMBER   LN_PO_NUMBER
300000136747640   300000006290049               K11004499
300000136747640
300000136747640
300000136747640   300000006290049               K11004499

CodePudding user response:

The below uses a CTE to give all INVOICE_IDs the same LN_PO_NUMBER.

If they can legitimately ever have different "non-NULL" PO_NUMBERs, this won't work.

Then your sub-query has been adapted to use ORDER BY REQ_BU_ID DESC FETCH NEXT 1 ROWS ONLY in order to find exactly one REQ_BU_ID in a deterministic way, preferring non-NULL values.

Again, if any PO_NUMBER can legitimately relate to more than 1 non-NULL REQ_BU_ID, this won't work.

Also, if ZERO REQ_BU_ID are found, it still returns NULL.

WITH
  PO_LOOKUP
AS
(
  SELECT
    HDR.INVOICE_ID,
    HDR.PO_NUMBER,
    MAX(LN.PO_NUMBER) OVER (PARTITION BY HDR.INVOICE_ID)   AS LN_PO_NUMBER
  FROM
    AP_INVOICES_INTERFACE        HDR
  INNER JOIN
    AP_INVOICE_LINES_INTERFACE   LN
      ON LN.INVOICE_ID = HDR.INVOICE_ID
)
SELECT
  PO_LOOKUP.*,
  (
    SELECT REQ_BU_ID
      FROM PO_HEADERS_ALL
     WHERE SEGMENT1 = PO_LOOKUP.LN_PO_NUMBER
  ORDER BY REQ_BU_ID ASC
     FETCH NEXT 1 ROWS ONLY
  )
    AS REQ_BU_ID
FROM
  PO_LOOKUP
WHERE
  INVOICE_ID = 300000136747640

Demo : https://dbfiddle.uk/N9fb6W9I

EDIT: Alternatively...

SELECT
  HDR.INVOICE_ID,
  HDR.PO_NUMBER,
  LN.MAX_PO_NUMBER,
  PO.MAX_REQ_BU_ID
FROM
  AP_INVOICES_INTERFACE        HDR
INNER JOIN
(
  SELECT
    AP_INVOICE_LINES_INTERFACE.*,
    MAX(PO_NUMBER) OVER (PARTITION BY INVOICE_ID)  AS MAX_PO_NUMBER
  FROM
    AP_INVOICE_LINES_INTERFACE
)
  LN
    ON LN.INVOICE_ID = HDR.INVOICE_ID
INNER JOIN
(
  SELECT
    SEGMENT1,
    MAX(REQ_BU_ID)   AS MAX_REQ_BU_ID
  FROM
    PO_HEADERS_ALL
  GROUP BY
    SEGMENT1
)
  PO
    ON PO.SEGMENT1 = LN.MAX_PO_NUMBER
WHERE
  HDR.INVOICE_ID = 300000136747640
  • Related