SQL 有条件的查询

SQL query with condition

所以我的销售订单中的每件商品都有一个 table,其中包含商品 ID 或仅包含描述(如果它不是真实商品),table 如下所示:

销售订单行:

|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                     |

我想做的是,如果它不是真实的项目(有 SOI_IMA_RecordID = NULL and/or SOI_LineNbrTypeCode = GL Acct)不要与我的项目进行内部连接 ​​table 并获取 SOI_MiscLineDescription 而不是项目名称(在我的查询中为 IMA_ItemName)。

我的查询如下:

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

怎么做?

您可以在 SELECT:

中使用 CASE 语句
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'

A​​ left join 将允许您在匹配 on 条件时加入,并且在不匹配时仍然仅显示加入右侧的列 - 在您的情况下,当 SOI_IMA_RecordIDnull:

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

将您的 INNER JOIN 更改为 LEFT JOIN 并使用 CASE 获得您想要的值:

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

这样只有在有记录匹配时才加入Itemtable,没有匹配记录时字段为NULL。当 CASE 不是 NULL 时,CASEItem table 中选择字段,否则选择描述。

编辑 - 我在输入答案时看到有两个人比我先到了!

因为您正在对项目使用 INNER JOIN,所以您的 SalesOrderLine 中没有相应 ITE.IMA_RecordID 的任何行都不会出现在您的最终查询中。

相反,对项目使用 LEFT JOIN,并使用确定要使用哪个描述的函数,或者简单地 return 两列(销售订单行的描述和项目的描述。)

我不太熟悉 SQL 服务器函数,但在 PostGres 和 MySql 中,这些函数就像 COALESCE() (return 中的第一个非空值字段列表)

我相信你可能想在这里使用 case 语句,比如

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