简体   繁体   中英

SQL: How to use CASE in join

Here is the code I am trying to use

SELECT
  TData.dtContractDate,
  TData.chPurchase,
  TData.nShipperID,
  TData.nSourceSiteId,
  Vendor.chShipperName,
  Vendor.chCity,
  Vendor.chState,
  Vendor.chCountry,
  Vendor.chZip 
FROM Data1.dbo.TData TData
JOIN Data1.dbo.Vendor
  ON Vendor.nShipperId = TData.nShipperID
  AND Vendor.nCompanyCode  = (CASE WHEN Vendor.nCompanyCode = '2' THEN '2' ELSE '26' END)
WHERE (TData.nCompanyCode=2) AND (TData.dtContractDate > '" 04/23/2015 12:01:00 AM')

I am trying to join these two tables, but if

ncompanycode = 2 AND Vendor.nShipperId = TData.nShipperID ,

then I want to pull that data, if this doesn't exist, then I want to use

ncompanycode = 26 and Vendor.nShipperId = TData.nShipperID .

Right now I get duplicates for any shipperID that both companies have.

Here are the dummy tables and the results I am getting, I don't want duplicates for chPurchase.

TData Table

|            dtContractDate | chPurchase | nShipperID | nSourceSiteId | nCompanyCode |
|---------------------------|------------|------------|---------------|--------------|
| January, 04 2015 00:00:00 |    2547635 |        453 |      68686868 |            2 |
| January, 05 2015 00:00:00 |    2547636 |        453 |      68686868 |            2 |
| January, 06 2015 00:00:00 |    2547637 |        454 |      68686868 |            2 |
| January, 07 2015 00:00:00 |    2547638 |        454 |      68686868 |            2 |
| January, 08 2015 00:00:00 |    2547639 |        455 |      68686868 |            2 |
| January, 09 2015 00:00:00 |    2547640 |        456 |      68686868 |            2 |

Vendor Table

| nCompanyCode | nShipperID | chShipperName | chCity | chState | chCountry |  chZip |
|--------------|------------|---------------|--------|---------|-----------|--------|
|            2 |        453 |         Name1 | Dallas |      TX |        US | 666555 |
|           26 |        453 |         Name2 | Dallas |      TX |        US | 666556 |
|            2 |        454 |         Name3 | Dallas |      TX |        US | 666557 |
|           26 |        455 |         Name4 | Dallas |      TX |        US | 666558 |
|            2 |        455 |         Name5 | Dallas |      TX |        US | 666559 |
|           26 |        456 |         Name6 | Dallas |      TX |        US | 666560 |

Results Table

|   dtContractDate | chPurchase | nShipperID | nSourceSiteId | nCompanyCode | chShipperName | chCity | chState | chCountry |  chZip |
|------------------|------------|------------|---------------|--------------|---------------|--------|---------|-----------|--------|
| January, 04 2015 |    2547635 |        453 |      68686868 |           26 |         Name2 | Dallas |      TX |        US | 666555 |
| January, 04 2015 |    2547635 |        453 |      68686868 |            2 |         Name1 | Dallas |      TX |        US | 666555 |
| January, 05 2015 |    2547636 |        453 |      68686868 |           26 |         Name1 | Dallas |      TX |        US | 666556 |
| January, 05 2015 |    2547636 |        453 |      68686868 |            2 |         Name2 | Dallas |      TX |        US | 666556 |
| January, 06 2015 |    2547637 |        454 |      68686868 |            2 |         Name3 | Dallas |      TX |        US | 666557 |
| January, 07 2015 |    2547638 |        454 |      68686868 |            2 |         Name3 | Dallas |      TX |        US | 666558 |
| January, 08 2015 |    2547639 |        455 |      68686868 |            2 |         Name5 | Dallas |      TX |        US | 666559 |
| January, 08 2015 |    2547639 |        455 |      68686868 |           26 |         Name5 | Dallas |      TX |        US | 666559 |
| January, 09 2015 |    2547640 |        456 |      68686868 |            26 |         Name6 | Dallas |      TX |        US | 666560 |

This solution does not use CASE but produces the desired result with cleaner conditionals using COALESCE .

I have shortened your table aliases for readability.

I have also commented out the WHERE clause involving dates because:

  1. It was mal-formed and would not match any date with current typos.
  2. When typos were corrected, it eliminates all rows from your sample data.

The SQL code uses two LEFT JOINs and uses COALESCE to choose which one to use in the SELECT output. When the first JOIN ( V ) has a NULL result, the output resorts to V2 . The V2 JOIN explicitly requires that the nCompanyCode be 26 , but any criteria can be added or removed as desired if there are multiple alternative nCompanyCodes .

Query:

SELECT
   T.dtContractDate
  ,T.chPurchase
  ,T.nShipperID
  ,T.nSourceSiteId
  ,COALESCE(V.chShipperName,V2.chShipperName) chShipperName
  ,COALESCE(V.chCity,V2.chCity) chCity
  ,COALESCE(V.chState, V2.chState) chState
  ,COALESCE(V.chCountry,V2.chCountry) chCountry
  ,COALESCE(V.chZip,V2.chZip) chZip
  -- Added to show what Vendor company code is being used
  ,COALESCE(V.nCompanyCode,V2.nCompanyCode) nCompanyCode
FROM TData T
LEFT JOIN Vendor V
  ON V.nShipperId = T.nShipperID
  AND V.nCompanyCode = T.nCompanyCode
LEFT JOIN Vendor V2
  ON V2.nShipperId = T.nShipperID
  AND V2.nCompanyCode <> T.nCompanyCode
  AND V2.nCompanyCode = 26
-- Commented out this WHERE clause because it eliminates all rows
-- WHERE T.dtContractDate > '04/23/2015 12:01:00 AM'

Sample Output:

|   dtContractDate | chPurchase | nShipperID | nSourceSiteId | chShipperName | chCity | chState | chCountry |  chZip | nCompanyCode |
|------------------|------------|------------|---------------|---------------|--------|---------|-----------|--------|--------------|
| January, 04 2015 |    2547635 |        453 |      68686868 |         Name1 | Dallas |      TX |        US | 666555 |            2 |
| January, 05 2015 |    2547636 |        453 |      68686868 |         Name1 | Dallas |      TX |        US | 666555 |            2 |
| January, 06 2015 |    2547637 |        454 |      68686868 |         Name3 | Dallas |      TX |        US | 666557 |            2 |
| January, 07 2015 |    2547638 |        454 |      68686868 |         Name3 | Dallas |      TX |        US | 666557 |            2 |
| January, 08 2015 |    2547639 |        455 |      68686868 |         Name5 | Dallas |      TX |        US | 666559 |            2 |
| January, 09 2015 |    2547640 |        456 |      68686868 |         Name6 | Dallas |      TX |        US | 666560 |           26 |

You can play with the SQLFiddle for this example here .

I think what you want is to join on the two tables where the shipper IDs are equal and then select all the rows from that set where the company code is equal to the value you want. Also, it seems like you don't want that WHERE (TData.nCompanyCode=2) condition, since you're already trying to select where the company code is 2 OR 26 above. Try this:

SELECT TData.dtContractDate, TData.chPurchase, TData.nShipperID, 
TData.nSourceSiteId,  Vendor.chShipperName, Vendor.chCity,     
Vendor.chState,  Vendor.chCountry, Vendor.chZip 
FROM Data1.dbo.TData TData
Join Data1.dbo.Vendor on Vendor.nShipperId = TData.nShipperID
WHERE Vendor.nCompanyCode  = (case when Vendor.nCompanyCode = '2' then     
'2' else '26' end)
AND (TData.dtContractDate > '" 04/23/2015     
12:01:00 AM')

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM