1

So I have a table for every item in my sales order, which contains the item ID or just a description if it's not a real item, the table looks like this:

SalesOrderLine:

|ID | SOI_IMA_RecordID | SOI_LineNbrTypeCode | SOI_MiscLineDescription |
|1  | 2                | Item                | XYZ                     |
|2  | NULL             | GL Acct             | Description             |
|3  | NULL             | GL Acct             | Descrip                 |
|4  | 20               | Item                | ABC                     |

What I want to do is, if it's not a real item (have the SOI_IMA_RecordID = NULL and/or SOI_LineNbrTypeCode = GL Acct) do not inner join with my Item table and get the SOI_MiscLineDescription instead of the item name (IMA_ItemName in my query).

My query is the following:

SELECT  SOH_ModifiedDate,
        SOM_SalesOrderID,
        IMA_ItemName,
        SOH_SOD_RequiredDate,
        SOD_RequiredDate,
        SOH_SOD_DockDate,
        SOD_DockDate,
        SOH_SOD_PromiseDate,
        SOD_PromiseDate,
        SOH_SOD_RequiredQty,
        SOD_RequiredQty,
        SOH_SOD_UnitPrice,
        SOD_UnitPrice
    FROM        WSI_SOH            SOH
    INNER JOIN  SalesOrderDelivery SOD   ON SOH.SOH_SOD_RecordID = SOD.SOD_RecordID
    INNER JOIN  SalesOrder         SO    ON SO.SOM_RecordID      = SOD.SOD_SOM_RecordID
    INNER JOIN  SalesOrderLine     SOI   ON SOI.SOI_RecordID     = SOD.SOD_SOI_RecordID
    INNER JOIN  Item               ITE   ON ITE.IMA_RecordID     = SOI.SOI_IMA_RecordID

How to do it?

2
  • 1
    And "it" refers to what? Commented Jun 3, 2015 at 16:23
  • Depending on your case you could use outer join for the other tables or split the fetch into 2 parts using union all and fetch the null rows separately Commented Jun 3, 2015 at 16:30

4 Answers 4

2

You can use the CASE statement in your SELECT:

SELECT CASE WHEN SOI_IMA_RecordID IS NULL OR
                 SOI_LineNbrTypeCode = 'GL Acct'
            THEN SOI_MiscLineDescription
            ELSE IMA_ItemName
       END ItemName,
       -- ...
FROM        WSI_SOH            SOH
INNER JOIN  SalesOrderDelivery SOD   ON SOH.SOH_SOD_RecordID = SOD.SOD_RecordID
INNER JOIN  SalesOrder         SO    ON SO.SOM_RecordID      = SOD.SOD_SOM_RecordID
INNER JOIN  SalesOrderLine     SOI   ON SOI.SOI_RecordID     = SOD.SOD_SOI_RecordID
LEFT  JOIN  Item               ITE   ON ITE.IMA_RecordID     = SOI.SOI_IMA_RecordID AND
                                        SOI_IMA_RecordID IS NOT NULL AND
                                        SOI_LineNbrTypeCode != 'GL Acct'
Sign up to request clarification or add additional context in comments.

2 Comments

And left join the Item table.
SOI_IMA_RecordID IS NOT NULL is redundant in the join condition. It's already implied by the comparison with ITE.IMA_RecordID.
0

A left join will allow you to join when the on condition is matched, and still display only the columns from the right side of the join when it isn't - in your case, when SOI_IMA_RecordID is null:

SELECT  SOH_ModifiedDate,
        SOM_SalesOrderID,
        IMA_ItemName,
        SOH_SOD_RequiredDate,
        SOD_RequiredDate,
        SOH_SOD_DockDate,
        SOD_DockDate,
        SOH_SOD_PromiseDate,
        SOD_PromiseDate,
        SOH_SOD_RequiredQty,
        SOD_RequiredQty,
        SOH_SOD_UnitPrice,
        SOD_UnitPrice
    FROM        WSI_SOH            SOH
    INNER JOIN  SalesOrderDelivery SOD   ON SOH.SOH_SOD_RecordID = SOD.SOD_RecordID
    INNER JOIN  SalesOrder         SO    ON SO.SOM_RecordID      = SOD.SOD_SOM_RecordID
    INNER JOIN  SalesOrderLine     SOI   ON SOI.SOI_RecordID     = SOD.SOD_SOI_RecordID
    LEFT JOIN   Item               ITE   ON ITE.IMA_RecordID     = SOI.SOI_IMA_RecordID

Comments

0

Change your INNER JOIN to a LEFT JOIN and use CASE to get the value you want:

SELECT  SOH_ModifiedDate,
...
        CASE 
            WHEN IMA_ItemName IS NULL THEN SOI_MiscLineDescription 
            ELSE IMA_ItemName END AS ItemName,
...
FROM        WSI_SOH            SOH
...
LEFT JOIN Item ITE ON ITE.IMA_RecordID = SOI.SOI_IMA_RecordID AND SOI_IMA_RecordID IS NOT NULL

This way, it only joins to the Item table when there is a record to match, and when there is no matching record, the fields are NULL. The CASE picks the field from the Item table when it is not NULL, and the description otherwise.

Edit - I see two people got there before me whilst I was typing my answer!

Comments

0

Because you're using an INNER JOIN on item, any rows in your SalesOrderLine that do not have a corresponding ITE.IMA_RecordID won't appear in your final query.

Instead, use a LEFT JOIN on item, and either use a function that determines which description to use, or simply return both columns (the description from SalesOrder Line and the description from Item.)

I'm not too familiar with SQL Server functions, but in PostGres and MySql, these functions are like COALESCE() (returns first non-null value in list of fields)

I believe you may want to use the case statement here, something like

case when item.description!=null 
then item.description 
else SalesOrderLine.SOI_MiscLineDescription 
end

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.