获取具有多种状态的项目的状态计数

时间:2017-05-31 16:25:24

标签: sql sql-server tsql

假设我有以下表变量:

DECLARE @DevicesAndStatuses TABLE (Id BIGINT,[Status] INT);

DECLARE @myId BIGINT;
SET @myId = 1;

在上面的表格中,我可以有数千个ID(Id可以重复),状态在1-50之间。获取特定Id的所有状态的最有效方法是什么?

我的传统方法如下:

SELECT 
(SELECT COUNT(*) FROM @DevicesAndStatuses WHERE Id = @myId AND [Status] = 1) AS Status1,
(SELECT COUNT(*) FROM @DevicesAndStatuses WHERE Id = @myId AND [Status] = 2) AS Status2,
(SELECT COUNT(*) FROM @DevicesAndStatuses WHERE Id = @myId AND [Status] = 3) AS Status3,
(SELECT COUNT(*) FROM @DevicesAndStatuses WHERE Id = @myId AND [Status] = 4) AS Status4,
...
(SELECT COUNT(*) FROM @DevicesAndStatuses WHERE Id = @myId AND [Status] = 50) AS Status50,

FROM @DevicesAndStatuses WHERE Id = @myId

是否有更好的解决方案来获取特定ID的所有状态[1-50]的计数?

最终结果应该是包含50列的单行,显示每个状态的计数(),如Status1,Status2,...,Status50。*

4 个答案:

答案 0 :(得分:2)

我的第一个建议是使用group by

SELECT status, count(*)
FROM @DevicesAndStatuses
WHERE Id = @myId
GROUP BY status;

获取所需信息的最简单方法,但需要多行。

如果您想要多列,请使用条件聚合:

SELECT SUM(CASE WHEN [Status] = 1 THEN 1 ELSE 0 END) AS Status1,
       SUM(CASE WHEN [Status] = 2 THEN 1 ELSE 0 END) AS Status2,
       SUM(CASE WHEN [Status] = 3 THEN 1 ELSE 0 END) AS Status3,
       SUM(CASE WHEN [Status] = 4 THEN 1 ELSE 0 END) AS Status4,
       . . .
FROM @DevicesAndStatuses
WHERE Id = @myId

答案 1 :(得分:1)

不确定

SELECT Status, COUNT(*)
FROM @DevicesAndStatuses 
WHERE Id = @myId    
GROUP BY Status

这会在一个简单的陈述中返回Status的所有Id = @myId值及其计数

答案 2 :(得分:0)

你去吧

SELECT MAX(id) AS Id, status, COUNT(*)
  FROM @DevicesAndStatuses
 WHERE Id = @myId
GROUP BY status;

SELECT id AS Id, status, COUNT(*)
  FROM @DevicesAndStatuses
 WHERE Id = @myId
GROUP BY id,status;

答案 3 :(得分:0)

您需要使用Dynamic Pivot Query来实现此目标:

我已经使用通用示例完成了它,但如果您需要更具体的版本,请戳我。您需要使用临时表而不是表变量。

STUFF命令可以从字符串的开头删除,

CREATE TABLE #Items
(
    Item INT IDENTITY(1,1),
    [Status] INT
)

INSERT #Items
(Status)
VALUES
(1),(1),(1),(1),(1),(1),(1),(2),(2),(2),(2),(3),(3),(4),(4),(4),(4),(4),(4),(4),(4),(5);


DECLARE @StatusList NVARCHAR(MAX) = N'',
        @SumSelector NVARCHAR(MAX) = N''

SELECT @StatusList = CONCAT(@StatusList, N',', QUOTENAME(s.Status)),
       @SumSelector = CONCAT(@SumSelector, N',', N'SUM(', QUOTENAME(s.Status), N') AS Status_', s.Status)
        FROM (SELECT DISTINCT [Status] FROM #Items) AS s

SELECT @StatusList = STUFF(@StatusList, 1, 1, N''),
       @SumSelector = STUFF(@SumSelector, 1, 1, N'')

DECLARE @StatusPivotQuery NVARCHAR(MAX) = CONCAT(N'

    SELECT ', @SumSelector, N'
    FROM #Items AS s
    PIVOT
    (
        COUNT(s.[Status])
        FOR s.[Status] IN(', @StatusList, N')
    ) AS pvt ')

EXEC sys.sp_executesql @StatusPivotQuery

DROP TABLE #Items