【问题标题】:How can I convert this PIVOT sql to CASE WHEN如何将此 PIVOT sql 转换为 CASE WHEN
【发布时间】:2022-08-18 23:46:09
【问题描述】:

我想将此 PIVOT 转换为 CASE WHEN,因为我读到 PIVOT 对大型数据库很慢。 可能吗? 我尝试转换它但失败了,它显示所有 cmdocumentdefn.code COUNT 是 50。我想按工作日计算代码,即

MON  TUE  WED .... SUN
8     2    4        1

查询是:

SELECT * FROM
    (SELECT 
        cmdocumentdefn.code, cmdocumentdefn.description \'description\',
        CASE DatePart(weekday,cmrevisionaddress.issueddate)
        WHEN 1 THEN \'SUN\'
        WHEN 2 THEN \'MON\'
        WHEN 3 THEN \'TUE\' 
        WHEN 4 THEN \'WED\'
        WHEN 5 THEN \'THU\'
        WHEN 6 THEN \'FRI\'
        WHEN 7 THEN \'SAT\'
        END  \'dayx\'    
    FROM cmdocumentdefn
        INNER JOIN
        cmdocument
        ON cmdocumentdefn.cmdocumentdefn = cmdocument.cmdocumentdefn
        INNER JOIN cmrevisionaddress
        ON cmdocument.cmdocument = cmrevisionaddress.cmdocument WHERE cmdocumentdefn.code = \'AF\') x
    PIVOT(COUNT(dayx) FOR dayx IN([MON],[TUE],[WED],[THU],[FRI],[SAT],[SUN])) pvt
  • SELECT COUNT(CASE WHEN (CASE DatePart(weekday,cmrevisionaddress.issueddate) WHEN 1 THEN \'SUN\' WHEN 2 THEN \'MON\' WHEN 3 THEN \'TUE\' WHEN 4 THEN \'WED\' WHEN 5 THEN \'THU\' WHEN 6 THEN \'FRI\' WHEN 7 THEN \'SAT\' END) = \'MON\' THEN \'MON\' ELSE \'\' END) AS MON ...我不是获得正确的 COUNT,它不是每个工作日的计数
  • 您能否提供示例数据和预期结果?
  • MON、TUE、WED 及其下方的标题是计数的。计数前的代码说明。我希望你明白我在说什么。我无法在此处格式化我的答案。

标签: sql sql-server pivot case


【解决方案1】:

您也可以将包含条件聚合的逻辑与SUM() 一起使用,例如

WITH d AS -- in order to generate fixed integers from 1 to 7 for the day of a week 
(
 SELECT 1 AS day_num
 UNION ALL
 SELECT day_num+1 FROM d WHERE day_num+1<=7
), cra AS
(
 SELECT DatePart(weekday, issueddate) AS day
   FROM d
   LEFT JOIN cmrevisionaddress
     ON DatePart(weekday, issueddate) = day_num
)
SELECT SUM(CASE WHEN day=2 THEN 1 ELSE 0 END) AS MON,
       SUM(CASE WHEN day=3 THEN 1 ELSE 0 END) AS TUE,
       SUM(CASE WHEN day=4 THEN 1 ELSE 0 END) AS WED,
       SUM(CASE WHEN day=5 THEN 1 ELSE 0 END) AS THU,
       SUM(CASE WHEN day=6 THEN 1 ELSE 0 END) AS FRI,
       SUM(CASE WHEN day=7 THEN 1 ELSE 0 END) AS SAT,
       SUM(CASE WHEN day=1 THEN 1 ELSE 0 END) AS SUN
  FROM cmdocumentdefn AS cdd
  JOIN cmdocument AS cd
    ON cdd.cmdocumentdefn = cd.cmdocumentdefn
  JOIN cra
    ON cd.cmdocument = cra.cmdocument
 WHERE cdd.code = 'AF'

Demo

【讨论】:

  • 我认为这些连接是不正确的。你需要FROM d LEFT JOIN cmrevisionaddress AS cra JOIN cmdocument AS cd ON ... ON ON DatePart(weekday, issueddate) = day_num 注意内连接是如何嵌套在左连接内的
  • 我尝试了您的解决方案,但没有得到我想要的。感谢您花在这方面的时间。非常感激!
  • 嗨@LeonardoVicenteRapirap,不客气。我认为共享一些 DDL 来表示表的创建,并且仅几行示例数据将有助于很好地重现问题。
  • 我无法在 db fiddle 中创建示例表,因为我没有帐户,而是使用数据和目标输出捕获了该表。 [paste.pics/1b2cfa33158a663b540f95c87c37995e - 表格] 和 [paste.pics/eab5c61b16a4d94673e1faa41a58872e - 目标输出]
【解决方案2】:
DECLARE @data TABLE (ID int, Code nvarchar(10), Description nvarchar(100), DocDate datetime) 
INSERT INTO @data VALUES(1, 'FA', 'lorem ipsum 1', '2021-07-05')
INSERT INTO @data VALUES(2, 'FA', 'lorem ipsum 2', '2021-07-05')
INSERT INTO @data VALUES(3, 'FA', 'lorem ipsum 3', '2021-07-05')
INSERT INTO @data VALUES(4, 'FA', 'lorem ipsum 4', '2021-07-05')
INSERT INTO @data VALUES(5, 'SH', 'lorem ipsum 5', '2021-08-31')
INSERT INTO @data VALUES(6, 'SH', 'lorem ipsum 6', '2021-08-31')
INSERT INTO @data VALUES(7, 'SH', 'lorem ipsum 7', '2021-08-31')
INSERT INTO @data VALUES(8, 'AG', 'lorem ipsum 8', '2021-09-15')
INSERT INTO @data VALUES(9, 'AG', 'lorem ipsum 9', '2021-09-15')
INSERT INTO @data VALUES(10, 'XX', 'lorem ipsum 10', '2021-10-21')


SELECT Code, Description, 
        IIF(DATEPART(weekday, DocDate) = 1, 1, 0) AS SUN,
        IIF(DATEPART(weekday, DocDate) = 2, 1, 0) AS MON,
        IIF(DATEPART(weekday, DocDate) = 3, 1, 0) AS TUE,
        IIF(DATEPART(weekday, DocDate) = 4, 1, 0) AS WED,
        IIF(DATEPART(weekday, DocDate) = 5, 1, 0) AS THU,
        IIF(DATEPART(weekday, DocDate) = 6, 1, 0) AS FRI,
        IIF(DATEPART(weekday, DocDate) = 7, 1, 0) AS SAT
FROM @data

我取了示例数据的前 10 行。这是结果:

如果您想要每个 code 的总和,那么这是查询:

SELECT Code,  
        SUM(IIF(DATEPART(weekday, DocDate) = 1, 1, 0)) AS SUN,
        SUM(IIF(DATEPART(weekday, DocDate) = 2, 1, 0)) AS MON,
        SUM(IIF(DATEPART(weekday, DocDate) = 3, 1, 0)) AS TUE,
        SUM(IIF(DATEPART(weekday, DocDate) = 4, 1, 0)) AS WED,
        SUM(IIF(DATEPART(weekday, DocDate) = 5, 1, 0)) AS THU,
        SUM(IIF(DATEPART(weekday, DocDate) = 6, 1, 0)) AS FRI,
        SUM(IIF(DATEPART(weekday, DocDate) = 7, 1, 0)) AS SAT
FROM @data
GROUP BY Code

结果:

【讨论】:

  • 我没有得到我想要的输出。我将尝试重写查询,看看我得到了什么。谢谢你的时间。高度赞赏!
  • @LeonardoVicenteRapirap 您能否提供一些具有预期结果的示例数据?想出解决方案会更容易,因为这个问题没有得到很好的解释。
  • 我无法在 db fiddle 中创建示例表,因为我没有帐户,而是使用数据和目标输出捕获了该表。 [paste.pics/1b2cfa33158a663b540f95c87c37995e - 表格] 和 [paste.pics/eab5c61b16a4d94673e1faa41a58872e - 目标输出]
  • @LeonardoVicenteRapirap 我编辑了我的原始答案以适应新提供的示例数据和预期结果。
猜你喜欢
  • 2021-08-18
  • 1970-01-01
  • 1970-01-01
  • 2020-11-29
  • 1970-01-01
  • 1970-01-01
  • 2021-01-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多