SQL Server => 如何在多列上使用“case when”来根据同一行中的条件显示公式结果

问题描述 投票:0回答:1

我正在尝试提供公式 ([CALCULATION]) 的总体结果,然后在两个额外的列 ([NO_TENURE] & [TENURE]) 中进行相同的计算,但使用“CASE WHEN”根据另一列过滤信息称为 [TENURE],所有内容都在一行中,如下所示:

MONTH       TYPE       CALCULATION                             NO_TENURE                               TENURE
----------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
1           TYPE1      5.33333333333                           5.33333333333                           6.81333333333

现在是这样显示的:

MONTH       TYPE       CALCULATION                             NO_TENURE                               TENURE
----------- ---------- --------------------------------------- --------------------------------------- ---------------------------------------
1           TYPE1      5.33333333333                           5.33333333333                           NULL
1           TYPE1      6.81333333333                           NULL                                    6.81333333333
1           TYPE2      5.55555555555                           5.55555555555                           NULL
1           TYPE2      5.95238095238                           NULL                                    5.95238095238

这是我使用的代码:

IF OBJECT_ID('TEMPDB..#TEST') IS NOT NULL DROP TABLE #TEST
GO

CREATE TABLE #TEST 
(
    MONTH INT,
    TYPE VARCHAR(10),
    TENURE INT,
    NUMERADOR INT,
    DENOMINADOR INT
)

INSERT INTO #TEST
VALUES  (1, 'TYPE1', 35, 320, 60),
        (1, 'TYPE1', 96, 511, 75),
        (1, 'TYPE2', 23, 400, 72),
        (1, 'TYPE2', 102, 500, 84);

SELECT MONTH
       ,TYPE
       ,(SUM(NUMERADOR)/CONVERT(DECIMAL(10,4) ,SUM(DENOMINADOR))) [CALCULATION]
       ,CASE WHEN TENURE < 90 THEN (SUM(NUMERADOR)/CONVERT(DECIMAL(10,4) ,SUM(DENOMINADOR))) END [NO_TENURE]
       ,CASE WHEN TENURE >= 90 THEN (SUM(NUMERADOR)/CONVERT(DECIMAL(10,4) ,SUM(DENOMINADOR))) END [TENURE]

FROM #TEST
GROUP BY MONTH,
       TYPE,
       TENURE

非常感谢您的帮助!

sql sql-server group-by case
1个回答
1
投票

您的 GROUP BY 中有 TENURE,这意味着源数据中的每个不同任期将在输出中得到不同的行。

如果你从那里拿走 TENURE,你会得到你想要的一排。您的 CASE 表达式将不起作用,因为它应该在聚合函数内部...

SELECT
   MONTH
  ,TYPE
  ,SUM(                            NUMERADOR    ) / CONVERT(DECIMAL(10,4), SUM(                            DENOMINADOR    )) [CALCULATION]
  ,SUM(CASE WHEN TENURE <  90 THEN NUMERADOR END) / CONVERT(DECIMAL(10,4), SUM(CASE WHEN TENURE <  90 THEN DENOMINADOR END)) [NO_TENURE]
  ,SUM(CASE WHEN TENURE >= 90 THEN NUMERADOR END) / CONVERT(DECIMAL(10,4), SUM(CASE WHEN TENURE >= 90 THEN DENOMINADOR END)) [TENURE]
FROM
  #TEST
GROUP BY
   MONTH,
   TYPE

下一个问题是如何避免大量重复。这是通过使用子查询、CTE 或应用函数在一个范围内定义表达式并在不同范围内使用它们来完成的。

WITH
  NORMALISED_RESULT AS
(
  SELECT
    MONTH,
    TYPE,
    IS_TENURED,
    SUM(NUMERADOR) / CONVERT(DECIMAL(10,4), SUM(DENOMINADOR)) AS CALCULATION
  FROM
    #TEST
  CROSS APPLY
  (
    SELECT
      CASE WHEN TENURE <  90 THEN 0
           WHEN TENURE >= 90 THEN 1
                             ELSE -1 END AS IS_TENURED
  )
    AS TENURE_CHECK
  GROUP BY
    GROUPING SETS(
      (MONTH, TYPE, IS_TENURED),
      (MONTH, TYPE)
    )
)

-- This next part just pivots the normalised results
-- It can be skipped if three rows of normalised results is acceptable.

SELECT
  MONTH,
  TYPE,
  MAX(CASE WHEN IS_TENURED IS NULL THEN CALCULATION END) AS CALCULATION,
  MAX(CASE WHEN IS_TENURED = 0     THEN CALCULATION END) AS NO_TENURE,
  MAX(CASE WHEN IS_TENURED = 1     THEN CALCULATION END) AS TENURE
FROM
  NORMALISED_RESULT
GROUP BY
  MONTH,
  TYPE

ELSE -1
仅在某些行有
NULL
的情况下才存在
TENURE
.

演示:db<>fiddle

© www.soinside.com 2019 - 2024. All rights reserved.