SQL 服务器:如何按值分组,多列 n 天

SQL Server : how to group by value, multiple columns for n days

我找不到解决这个问题的方法,而且我的 SQL 技能很差,所以如果可以的话,也许有人可以提供建议。

环境:Microsoft SQL Server 2008 R2

当前的查询很简单,选择错误码的值,统计错误的个数,对错误码进行分组:

查询:

SELECT 
    ErrorCode AS EC, COUNT(*) as NoEr 
FROM 
    [DB].[dbo].[Table] 
WHERE
    ERRORTIME > '2018-12-30 00:00:00' 
    AND ERRORTIME < '2018-12-30 23:59:59' 
GROUP BY
    errorcode 
ORDER BY 
    ERRORCODE ASC

输出:

+----+-------+
| EC |  NoEr |  
+----+-------+
| A9 |  3333 | 
| E0 |  1505 |
| G9 |  1233 | 
| X1 |  2    | 
+----+-------+

我想获取最近 5 天的错误计数,如下所示:

+----+-------+-------+-------+-------+-------+
| EC |  MON  |  TUE  |  WED  |  THU  |  FRI  |
+----+-------+-------+-------+-------+-------+
| A9 |  1505 |  2333 |       |  1555 |  9999 |
| E0 |  3333 |       |  2311 |  5555 |  14   |
| G9 |  2222 |  1505 |   123 |  1233 |       |
| X1 |  1212 |  1233 |  1155 |  3    |       |
+----+-------+-------+-------+-------+-------+

谢谢你,祝你新年快乐!

您可以使用数据透视运算符来实现您的目标。

SELECT 
EC,[MON],[TUE],[WED],[THU],[FRI]
FROM 
(
SELECT 
ErrorCode AS EC,UPPER(LEFT(DATENAME(DW,ERRORTIME),3)) AS D_W, 1 AS NUMBER FROM [DB].[dbo].[Table]
WHERE DATEDIFF(DAY,ERRORTIME,GETDATE())<=5
) SRC
PIVOT
(
SUM(NUMBER) FOR D_W IN ([MON],[TUE],[WED],[THU],[FRI])
) PVT

此致,

您可以使用 CASE 表达式和聚合 SUM 来计算每个工作日的计数,如下所示 -

Select 
    ErrorCode as EC,
    SUM(CASE WHEN Datename(w, ErrorTime) = 'Monday' THEN 1 ELSE 0 END) as MON,
    SUM(CASE WHEN Datename(w, ErrorTime) = 'Tuesday' THEN 1 ELSE 0 END) as TUE,
    SUM(CASE WHEN Datename(w, ErrorTime) = 'Wednesday' THEN 1 ELSE 0 END) as WED,
    SUM(CASE WHEN Datename(w, ErrorTime) = 'Thursday' THEN 1 ELSE 0 END) as THU,
    SUM(CASE WHEN Datename(w, ErrorTime) = 'Friday' THEN 1 ELSE 0 END) as FRI
From
    [DB].[dbo].[Table]
where 
    ERRORTIME > '2018-12-30 00:00:00' and ERRORTIME < '2018-12-30 23:59:59' 
group by errorcode 
order by ERRORCODE ASC

就像 Will 他说最好的选择是使用 PIVOT:

SELECT 
    *
FROM
(
    SELECT 
        ErrorCode AS                               EC, 
        UPPER(LEFT(DATENAME(DW, ERRORTIME), 3)) AS DayW, 
        1 AS                                   Number
    FROM 
         table_name
    WHERE
                ERRORTIME > = DATEADD(day, -5, GetDate())
) AS Source PIVOT(SUM(Number) FOR DayW IN(
    [MON], 
    [TUE], 
    [WED], 
    [THU], 
    [FRI])) PVT

你想要过去五天的结果,而不是一天的结果,所以我想你想要:

SELECT ErrorCode as EC,
       SUM(CASE WHEN datename(weekday, ErrorTime) = 'Monday' THEN 1 ELSE 0 END) as MON,
       SUM(CASE WHEN datename(weekday, ErrorTime) = 'Tuesday' THEN 1 ELSE 0 END) as TUE,
       SUM(CASE WHEN datename(weekday, ErrorTime) = 'Wednesday' THEN 1 ELSE 0 END) as WED,
       SUM(CASE WHEN datename(weekday, ErrorTime) = 'Thursday' THEN 1 ELSE 0 END) as THU,
       SUM(CASE WHEN datename(weekday, ErrorTime) = 'Friday' THEN 1 ELSE 0 END) as FRI
FROM [DB].[dbo].[Table] t
WHERE ERROR_TIME >= DATEADD(DAY, -5, CAST(GETDATE() as DATE)) AND
      ERROR_TIME >= CAST(GETDATE() as DATE)
GROUP BY errorcode 
ORDER BY ERRORCODE ASC;

请注意,当您使用 DATEADD()DATENAME() 等函数时,您应该 而不是 使用缩写。那只是一个糟糕的查询编写习惯。没有人愿意记住 w 是指 "week" 还是 "weekday" 或者 m 是指 "minute" 还是 "month"。使用全名,避免歧义。

如果您愿意,还可以将其简化为:

SELECT ErrorCode as EC,
       SUM(CASE WHEN ErrorTime_weekday = 'Monday' THEN 1 ELSE 0 END) as MON,
       SUM(CASE WHEN ErrorTime_weekday = 'Tuesday' THEN 1 ELSE 0 END) as TUE,
       SUM(CASE WHEN ErrorTime_weekday = 'Wednesday' THEN 1 ELSE 0 END) as WED,
       SUM(CASE WHEN ErrorTime_weekday = 'Thursday' THEN 1 ELSE 0 END) as THU,
       SUM(CASE WHEN ErrorTime_weekday = 'Friday' THEN 1 ELSE 0 END) as FRI
FROM [DB].[dbo].[Table] t CROSS APPLY
     (VALUES (datename(weekday, ErrorTime) = 'Thursday' THEN 1 ELSE 0 END))
     ) v(ErrorTime_weekday)
WHERE ERROR_TIME >= DATEADD(DAY, -5, CAST(GETDATE() as DATE)) AND
      ERROR_TIME >= CAST(GETDATE() as DATE)
GROUP BY errorcode 
ORDER BY ERRORCODE ASC;