【问题标题】:Count unique combination of multiple fields in a table with group by, returning only summary rows使用分组计算表中多个字段的唯一组合,仅返回汇总行
【发布时间】:2021-03-24 15:12:38
【问题描述】:

我有一张桌子:

VALA VALB DATE POST VALC
A C April 1, 2021 10001 D
B A April 1, 2021 10001 A
A A March 1, 2021 10001 A
A A March 1, 2021 10001 B
A B March 1, 2021 10001 A
A C March 1, 2021 10001 D
B A March 1, 2021 10001 A
A A April 1, 2021 10002 A
A A April 1, 2021 10002 A
A C April 1, 2021 10002 D
B A April 1, 2021 10002 A
A A March 1, 2021 10002 A
A A March 1, 2021 10002 A
A A March 1, 2021 10002 A
A A March 1, 2021 10002 A
A C March 1, 2021 10002 D
B A March 1, 2021 10002 A

我需要以下格式的结果集:

POST DATE COUNT
10001 March 1, 2021 5
10001 April 1, 2021 2
10002 March 1, 2021 3
10002 April 1, 2021 3

我尝试过的:

SELECT [POST]
,[DATE]
,COUNT(*) OVER(PARTITION BY [POST]) AS [COUNT]
FROM [TABLE]
GROUP BY [POST], [DATE]

这个问题: 获取VALA、VALB、VALC 字段的唯一组合的COUNT 的逻辑缺失。分组好像没问题,就是不知道怎么继续。

给你的虚拟数据:

CREATE TABLE [TABLE] (
    [VALA] varchar(255),
    [VALB] varchar(255),
    [DATE] varchar(255),
    [POST] varchar(255),
    [VALC] varchar(255),
);

INSERT INTO [TABLE]
VALUES
('A', 'A', 'March 1, 2021', 10001, 'A'),
('A', 'A', 'March 1, 2021', 10001, 'B'),
('A', 'B', 'March 1, 2021', 10001, 'A'),
('B', 'A', 'March 1, 2021', 10001, 'A'),
('A', 'C', 'March 1, 2021', 10001, 'D'),
('B', 'A', 'April 1, 2021', 10001, 'A'),
('A', 'C', 'April 1, 2021', 10001, 'D'),
('A', 'A', 'March 1, 2021', 10002, 'A'),
('A', 'A', 'March 1, 2021', 10002, 'A'),
('B', 'A', 'March 1, 2021', 10002, 'A'),
('A', 'C', 'March 1, 2021', 10002, 'D'),
('A', 'A', 'March 1, 2021', 10002, 'A'),
('A', 'A', 'March 1, 2021', 10002, 'A'),
('A', 'A', 'April 1, 2021', 10002, 'A'),
('B', 'A', 'April 1, 2021', 10002, 'A'),
('A', 'C', 'April 1, 2021', 10002, 'D'),
('A', 'A', 'April 1, 2021', 10002, 'A');

SELECT * FROM [TABLE]

谢谢。

【问题讨论】:

  • 附注:请避免将日期存储为文本,因为它不会正确排序。请改用实际的日期列。

标签: sql sql-server tsql


【解决方案1】:

一种方法使用DENSE_RANK 来计算三个值列的不同组合的数量。然后,我们可以按日期和帖子聚合,并取这个密集排名的最大值。

WITH cte AS (
    SELECT *, DENSE_RANK() OVER (PARTITION BY DATE, POST
                                 ORDER BY [VALA], [VALB], [VALC]) dr
    FROM yourTable
)

SELECT POST, DATE, MAX(dr) AS COUNT
FROM cte
GROUP BY POST, DATE
ORDER BY POST, DATE;

Demo

【讨论】:

  • 谢谢,看起来不错!我可以请你看看我的解决方案,如果这也可以吗?
【解决方案2】:

您可能想尝试以下方法:

SELECT [POST], [DATE], COUNT(DISTINCT CONCAT([FUND], [GRANT], [WBS])) AS [COUNT]
  FROM [TABLE]
  GROUP BY [POST], [DATE]

我猜像COUNT OVER 这样的窗口函数没有意义......

【讨论】:

    【解决方案3】:

    我刚刚发布了这个问题,但是我正在尝试解决这个问题超过 5 个小时,似乎我找到了解决方案:

    SELECT [POST]
    ,[DATE]
    ,COUNT(DISTINCT CONCAT([VALA], [VALB], [VALC])) AS [COUNT]
    FROM [TABLE2]
    GROUP BY [POST]
    ,[DATE]
    ORDER BY [POST] ASC, [DATE] DESC
    

    【讨论】:

    • 此解决方案存在潜在问题。假设VAL 列可以是一个 两个字母。那么(A, AB, C) 似乎与(AA, B, C) 相同。考虑使用类似我的答案的内容来避免这个陷阱。
    • 确实如此!如果在字段值之间插入一个字符怎么办? CONCAT([VALA],'#',[VALB],'#'[VALC]))。如果我们假设 # 不会出现在列的值中,这将把这个问题的风险降低到零。
    • 是的,然后以这种方式使用CONCAT 会使SQL Server 在查找计数时很难使用任何类型的索引。不要以低俗的自我推销者的身份出现,但如果网站允许我:-),我会在这里投票支持我自己的答案
    • 如果我需要使用 SQLite 的解决方案该怎么办?我应该发布另一个问题,还是更新这个问题? :/ 在这种情况下,我使用 SQL Server 开发查询,但我将使用该查询的应用程序使用 SQLite。
    • 在最新版本的 SQLite 上,我的回答应该也适合你。
    猜你喜欢
    • 1970-01-01
    • 2022-01-27
    • 1970-01-01
    • 2011-06-09
    • 1970-01-01
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多