Sql 当 A = Z 则设置 B = X

Sql When A = Z then set B = X

我似乎无法运行此查询,它一直告诉我“消息 102,级别 15,状态 1,第 5 行 '=' 附近的语法不正确。”不确定我在这里做错了什么。

基本上我需要 [forwarder_preferred_status] 为 P2 或 P3,具体取决于 [forwarder_short]

的值

欢迎提出任何建议

        Select 
            [forwarder_display],
            Case [forwarder_preferred_status]
            -- Update P2 Customers
                When [forwarder_short] = 'ABL' THEN [forwarder_preferred_status] = 'P2'
                When [forwarder_short] = 'ALK' THEN [forwarder_preferred_status] = 'P2'
                When [forwarder_short] = 'EIF' THEN [forwarder_preferred_status] = 'P2'
                When [forwarder_short] = 'NNR' THEN [forwarder_preferred_status] = 'P2'
                When [forwarder_short] = 'ALI' THEN [forwarder_preferred_status] = 'P2'
                When [forwarder_short] = 'LAF' THEN [forwarder_preferred_status] = 'P2'
                When [forwarder_short] = 'AIT' THEN [forwarder_preferred_status] = 'P2'
            -- Update P3 Customers
                When [forwarder_short] = 'SCHBAX' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'UPS' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'KUE' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'AGI' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'PAN' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'DGF' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'NEC' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'HWE' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'NIS' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'BDP' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'KWE' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'CEVA' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'VIZ' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'FTN' THEN [forwarder_preferred_status] = 'P3'
                When [forwarder_short] = 'UTI' THEN [forwarder_preferred_status] = 'P3'
            -- Fix wrong prefered status
                When [forwarder_short] = 'OIA' THEN [forwarder_preferred_status] = null
                When [forwarder_short] = 'PHO' THEN [forwarder_preferred_status] = null
                When [forwarder_short] = 'REI' THEN [forwarder_preferred_status] = null
                Else [forwarder_preferred_status]
            End as [forwarder_preferred_status]
            Sum ([calc_gross_rev]) As [Gr Revenue]
            Sum ([charge_weight]) As [Ch Weight]
        From 
            [dbo].[report_bo_awb_revenue_all]

        Where 
            [yr] = 2014
            AND [agent_iata_code] not in ('0508634','0514616')

您不需要在 CASE 语句的 THEN 部分指定字段名称,您可以在比较完成时删除第一个 WHEN 之前的语法在每个 WHEN 子句中:

CASE WHEN [forwarder_short] = 'ABL' THEN 'P2'...
End as [forwarder_preferred_status]

另一种方法是使用 IN 子句来保存一些字符:

CASE WHEN [forwarder_short] IN('ABL','ALK','EIF'...) THEN 'P2'...
End as [forwarder_preferred_status]

您使用 as(或在表达式前使用 =)在 case 之后为 添加别名 。像这样:

      (Case When [forwarder_short] = 'ABL' THEN 'P2'
            When [forwarder_short] = 'ALK' THEN 'P2'
            . . .
       End) as forwarder_preferred_status

或(Aaron Bertrand 喜欢但我不喜欢):

      forwarder_preferred_status = (Case When [forwarder_short] = 'ABL' THEN 'P2'
                                         When [forwarder_short] = 'ALK' THEN 'P2'
                                         . . .
                                    End);

另外,您在case后的表达式与when中布尔表达式的使用不一致。这只是坚持使用布尔表达式的情况的形式。

您可以使用 in:

大大简化您的逻辑
        (case when forwarder_short in ('ABL', 'ALK', 'EIF', 'NNR', 'ALI', 'LAF', 'AIT')
              then 'P2'
              . . .
         end) as forwarder_preferred_status

你问题中的代码结构如下:

--Bad
CASE A
    WHEN X THEN A = B
    WHEN Y THEN A = C
    ...
END

相反,您需要像这样构造它:

--Good
A = CASE
       WHEN X THEN B
       WHEN Y THEN C 
       ...
    END

或者像这样:

--Good
CASE
   WHEN X THEN B
   WHEN Y THEN C 
   ...
END As A

case 语句仅产生 ,而不是表达式。它不会在任意代码之间分支。此外,假设您有很多代码产生相同的值,您可以大大 简化这样的事情:

--Better
CASE
   WHEN X IN (1,2,3) THEN B
   WHEN X IN (4,5,6) THEN C
   ...
   ELSE NULL
END

看起来像这样:

Select 
    [forwarder_display],
    CASE 
        WHEN [forwarder_short] IN ('ABL', 'ALK', 'EIF', 'NNR', 'ALI', 'LAF', 'AIT')
          THEN 'P2' 
        WHEN [forwarder_short] IN ('SCHBAX', 'UPS', 'KUE', 'AGI', 'PAN', 'DGF', 'NEC', 
                                   'HWE', 'NIS', 'BDP', 'KWE', 'CEVA', 'VIZ', 'FTN', 'UTI') 
           THEN 'P3'
        WHEN [forwarder_short] IN ('OIA','PHO', 'REI')
           THEN NULL
        ELSE [forwarder_preferred_status]
    END as [forwarder_preferred_status],
    Sum ([calc_gross_rev]) As [Gr Revenue],
    Sum ([charge_weight]) As [Ch Weight]
From 
    [dbo].[report_bo_awb_revenue_all]

Where 
    [yr] = 2014
    AND [agent_iata_code] not in ('0508634','0514616')

不幸的是,这仍然不起作用,因为您缺少使 SUM() 聚合函数起作用所需的 GROUP BY 子句。由于表达式复杂,我发现通过嵌套查询更容易解决问题,如下所示:

SELECT forwarder_display, [forwarder_preferred_status],
    SUM([calc_gross_rev]) As [Gr Revenue],
    SUM([charge_weight]) As [Ch Weight]
FROM 
(
    Select 
        [forwarder_display], 
        CASE 
            WHEN [forwarder_short] IN ('ABL', 'ALK', 'EIF', 'NNR', 'ALI', 'LAF', 'AIT')
              THEN 'P2' 
            WHEN [forwarder_short] IN ('SCHBAX', 'UPS', 'KUE', 'AGI', 'PAN', 'DGF', 'NEC', 
                                       'HWE', 'NIS', 'BDP', 'KWE', 'CEVA', 'VIZ', 'FTN', 'UTI') 
               THEN 'P3'
            WHEN [forwarder_short] IN ('OIA','PHO', 'REI')
               THEN NULL
            ELSE [forwarder_preferred_status]
        END as [forwarder_preferred_status],
        [calc_gross_rev],
        [charge_weight]
    From 
        [dbo].[report_bo_awb_revenue_all]

    Where 
        [yr] = 2014
        AND [agent_iata_code] not in ('0508634','0514616')
) t
GROUP BY [forwarder_display], [forwarder_preferred_status]

这应该 运行 并给你想要的结果,除非出现一些错误(很有可能,因为我在答案 window 中输入了所有这些未经测试的内容)。但是,您可能会发现仅通过 copy/pasting 对 GROUP BY 子句的复杂 CASE 表达式就可以获得更好的执行计划,而无需嵌套查询。

最后,像这样的代码——所有这些 3 位和 4 位代码都被硬编码了——要求将这些代码放入 table,以便通过 JOIN + 完成COALESCE,而不是 CASE。这将 MUCH 提高性能和维护。那将允许你写这样的东西:

--Best
SELECT [forwarder_display],
    COALESCE(M.status, A.forwarder_preferred_status) As forwarder_preferred_status
    Sum ([calc_gross_rev]) As [Gr Revenue],
    Sum ([charge_weight]) As [Ch Weight]
FROM [dbo].[report_bo_awb_revenue_all] A
LEFT JOIN forwarder_map M ON m.forwarder_short = A.forwarder_short
WHERE
    A.[yr] = 2014
    AND [agent_iata_code] not in ('0508634','0514616')
GROUP BY [forwarder_display], COALESCE(M.status, A.forwarder_preferred_status)

最后一点:要使上面的示例起作用,您需要使用空字符串而不是虚构 forwarder_map table 中的 NULL 值。然后,您可以使用 NULLIF() 取回 NULL,如果这确实是您需要的。

你的陈述很难read/edit...你可以使用shorter/simpler方式..像这样:

SELECT [forwarder_display],
      CASE 
        WHEN [forwarder_short] IN ('ABL','ALK','NNR','EIF','ALI','LAF','AIT') THEN 'P2' 
        WHEN [forwarder_short] IN ('SCHBAX', 'UPS', 'KUE','AGI','PAN'......) THEN 'P3'
        WHEN [forwarder_short] IN ('OIA','PHO','REI') THEN null
      ELSE [forwarder_preferred_status]
      END AS forwarder_preferred_status
      ...

我敢打赌,这不是第一次有人需要将 ABL 翻译成 P2 来制作报告,也不会是最后一次。正如@Aaron 指出的那样,停止这些可怕的案例陈述并将其表格化。

为了这个答案,我使用了一个 table 变量。这些通常是不可取的,因为数据库引擎不会记录任何关于其中的值及其分布的统计信息,这是制定良好查询计划的关键。

DECLARE
    @TRANSLATE table
(
    forwarder_short varchar(10) NOT NULL
,   forwarder_preferred_status varchar(10) NULL
);

INSERT INTO
    @TRANSLATE
(
    forwarder_short
,   forwarder_preferred_status
)
VALUES
    ('ABL', 'P2')
,   ('ALK', 'P2')
,   ('EIF', 'P2')
,   ('NNR', 'P2')
,   ('ALI', 'P2')
,   ('LAF', 'P2')
,   ('AIT', 'P2')
,   ('SCHBAX', 'P3')
,   ('UPS', 'P3')
,   ('KUE', 'P3')
,   ('AGI', 'P3')
,   ('PAN', 'P3')
,   ('DGF', 'P3')
,   ('NEC', 'P3')
,   ('HWE', 'P3')
,   ('NIS', 'P3')
,   ('BDP', 'P3')
,   ('KWE', 'P3')
,   ('CEVA', 'P3')
,   ('VIZ', 'P3')
,   ('FTN', 'P3')
,   ('UTI', 'P3')
,   ('OIA', NULL)
,   ('PHO', NULL)
,   ('REI', NULL);

现在我有一个 table、TRANSLATE,它提供了我们已知的 forwarder_short 值到汇总 forwarder_preferred_status 之间的映射。

为了涵盖 forwarder_short 值不在此 table 中的情况,我们需要使用我们的翻译 table 作为 OUTER JOIN。

WITH report_bo_awb_revenue_all AS
(
    -- simulating your source data
    SELECT
        T.forwarder_short
    ,   T.forwarder_preferred_status
    ,   100 AS calc_gross_rev
    ,   12 AS charge_weigh
    ,   2014 AS yr
    ,   '' AS agent_iata_code
    ,   'fwd' AS forwarder_display
    FROM
        @TRANSLATE AS T
    UNION ALL
    SELECT
        'UNK'
    ,   'P90x'
    ,   9000 AS calc_gross_rev
    ,   12 AS charge_weigh
    ,   2014 AS yr
    ,   '' AS agent_iata_code
    ,   'fwd' AS forwarder_display
)
SELECT
    R.forwarder_display
,   COALESCE(T.forwarder_preferred_status, R.forwarder_preferred_status) AS forwarder_preferred_status
,   SUM(R.calc_gross_rev) AS calc_gross_rev
,   SUM(R.charge_weigh) AS charge_weigh
FROM
    report_bo_awb_revenue_all AS R
    LEFT OUTER JOIN
        @TRANSLATE AS T
        ON T.forwarder_short = R.forwarder_short
WHERE
    R.yr = 2014
    AND R.agent_iata_code not in ('0508634','0514616')
GROUP BY
    R.forwarder_display
,   T.forwarder_preferred_status
,   R.forwarder_preferred_status;

现在,所有的业务逻辑都被提炼成了这个

,   COALESCE(T.forwarder_preferred_status, R.forwarder_preferred_status) AS forwarder_preferred_status

"Use the value in our translate table if it exists, otherwise, use what's stored on the report_bo_awb_revenue_all table."

SQLFiddle version 这使用临时 table 进行翻译,因为 fiddle 不处理 table 变量,但核心概念仍然存在。