在SQL Server中按总数进行分组

时间:2018-09-08 23:13:00

标签: sql sql-server subquery

我有一个带有“项目”列的SQL表,我想按降序显示每个项目在总计数中所占的百分比。

例如

Column A
Item 1
Item 1
Item 2
Item 3

我想显示:

Column A
Item 1   0.5
Item 2   0.25
Item 3   0.25

到目前为止,我已经尝试了以下方法:

SELECT [Column A], (count([Column A]) / count(*))
  FROM [table]
  GROUP BY [Column A]
  Order by (count([Column A]) / count(*)) DESC

但是,一切恢复为1。

3 个答案:

答案 0 :(得分:1)

您可以尝试在主查询中按COUNT项对[Column A]进行分组。然后在子查询中进行总计count的除法。

CREATE TABLE T(
   [Column A] VARCHAR(50)
); 

INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 2');
INSERT INTO T VALUES ('Item 3');

SELECT [Column A],COUNT(*) /CAST ((SELECT COUNT(*) FROM T) AS FLOAT)
FROM T 
GROUP BY [Column A]

sqlfiddle

或者您可以使用CROSS JOIN得到总数然后进行除法。

SELECT [Column A],COUNT(*) /CAST(total AS FLOAT)
FROM T CROSS JOIN (SELECT COUNT(*) total FROM T) v
GROUP BY [Column A],total

答案 1 :(得分:0)

您的问题是,无论您的汇总如何应用于分组列,您都需要以某种方式分别获取总计。一种方法是像@ D-Shih一样使用派生表。我只是将其存储在变量中。

您遇到的另一个问题是两个操作数都为INT,因此SQL Server会为结果推断INT的数据类型。您只需要一个操作数即可不返回整数数据类型。我使用了精确的数值数据类型,因为如果以后您需要对各个%求和以获得100%,则近似数值可能会导致问题。

DECLARE @t_item TABLE
(       name VARCHAR(10)
)

DECLARE @total_count NUMERIC(3,2)

INSERT INTO @t_item
VALUES ('ITEM1'),
       ('ITEM1'),
       ('ITEM2'),
       ('ITEM3'),
       ('ITEM3'),
       ('ITEM1')

SELECT @total_count = COUNT(*) FROM @t_item

SELECT name,
       COUNT(name),
       COUNT(*),
       pct_of_all      = CONVERT(NUMERIC(3,2),COUNT(name))/CONVERT(NUMERIC(3,2),COUNT(*))
  FROM @t_item
 GROUP BY name


SELECT name,
       COUNT(name),
       @total_count,
       pct_of_all      = COUNT(name)/@total_count
  FROM @t_item
 GROUP BY name

答案 2 :(得分:0)

我认为Window函数对于这种情况是一种更好的解决方案,因为该表只能读取一次。

是否必须创建一个百分比,一个平均值和一个总和来代替一个百分比?还是查询比单个计数更复杂?创建许多子查询不是一种选择。因此,这就是我更喜欢窗口函数而不是子查询的原因。

dbfiddle

CREATE TABLE T(
   [Column A] VARCHAR(50)
); 

INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 1');
INSERT INTO T VALUES ('Item 2');
INSERT INTO T VALUES ('Item 3');

SELECT
   [Column A], CNT / SUM(CNT) OVER () PERC
FROM (
  SELECT [Column A], CAST(COUNT(*) AS NUMERIC) CNT
  FROM T 
  GROUP BY [Column A]
) X
ORDER BY PERC