计算 SQL 表中关于列的相同记录
Posted
技术标签:
【中文标题】计算 SQL 表中关于列的相同记录【英文标题】:Counting identical records in a SQL table with respect to a column 【发布时间】:2021-02-21 07:29:10 【问题描述】:问题描述
我正在寻找一个可以使用表 1 创建表 2 的 SQL 查询。我已经想到了这样做的方法,但它不是很有说服力,如果可能的话,我更喜欢更简单的方法。
表 1:
ID | Col_1 | Col_2 | Col_3 | Col_4 |
---|---|---|---|---|
01 | A | Q | R | U |
02 | A | Q | R | P |
03 | A | Q | R | U |
04 | A | Q | R | P |
05 | A | Q | T | U |
06 | A | Q | T | P |
07 | A | Q | T | U |
08 | A | Q | T | P |
09 | A | Q | R | U |
10 | B | Q | R | P |
11 | B | Q | R | U |
12 | B | Q | R | P |
13 | B | Q | T | U |
14 | C | Q | T | P |
15 | C | Q | T | U |
16 | C | Q | T | U |
17 | C | Q | R | P |
18 | C | Q | R | U |
19 | C | Q | R | P |
20 | C | Q | R | U |
表 2:
ID | Col_1 | Col_2 | Col_3 | Col_4 |
---|---|---|---|---|
01 | 9 | 9 | 5 | 3 |
02 | 9 | 9 | 5 | 2 |
03 | 9 | 9 | 5 | 3 |
04 | 9 | 9 | 5 | 2 |
05 | 9 | 9 | 4 | 2 |
06 | 9 | 9 | 4 | 2 |
07 | 9 | 9 | 4 | 2 |
08 | 9 | 9 | 4 | 2 |
09 | 9 | 9 | 5 | 3 |
10 | 4 | 4 | 3 | 2 |
11 | 4 | 4 | 3 | 1 |
12 | 4 | 4 | 3 | 2 |
13 | 4 | 4 | 1 | 1 |
14 | 7 | 7 | 3 | 1 |
15 | 7 | 7 | 3 | 2 |
16 | 7 | 7 | 3 | 2 |
17 | 7 | 7 | 4 | 2 |
18 | 7 | 7 | 4 | 2 |
19 | 7 | 7 | 4 | 2 |
20 | 7 | 7 | 4 | 2 |
表2中的数字生成如下:
在表 2 的 Col_1 中,数字是所有具有相同 Col_1 值的 ID 的计数。 在表 2 的 Col_2 中,数字是具有相同 Col_1 AND Col_2 值的所有 ID 的计数。 在表 2 的 Col_3 中,数字是具有相同 Col_1 的所有 ID 的计数 AND Col_2 AND Col_3价值。 在表 2 的 Col_4 中,数字是具有相同 Col_1 的所有 ID 的计数 AND Col_2 AND Col_3 AND Col_4 值。
示例: 在表 1 中,ID01 的 Col_1 值为“A”。 “A”与 02、03、04、05、06、07、08 和 09(其他 8 个 ID)匹配,因此数字为 9。 ID01 的 Col_2 值为“Q”。 Col_1 中的“A”AND Col_2 中的“Q”与 02、03、04、05、06、07、08 和 09(8 个其他 ID)匹配,因此数字是 9。 ID01 的 Col_3 值为“R”。 Col_1 中的“A”AND Col_2 中的“Q”AND Col_3 中的“R”与 02、03 匹配、04 和 09(4 个其他 ID),所以数字是 5。 ID01 的 Col_4 值为“U”。 Col_1 中的“A”AND Col_2 中的“Q”AND Col_3 中的“R”AND Col_4 中的“U”与 03 和 09(另外 2 个 ID)匹配,因此数字为 3。
基本上,我们试图在表 1 中找到相同 ID 的总数 - 相对于感兴趣的 Col。
我尝试过的
我想出了一种方法来获取表 2 中的数字,使用简短的 SQL 查询:
-- Somehow use in Table 2
SELECT
col_1,
col_2,
col_3,
col_4,
COUNT() AS ct
FROM sample_table
GROUP BY
col_1,
col_2,
col_3,
col_4
ORDER BY ct DESC;
返回
Col_1 | Col_2 | Col_3 | Col_4 | ct |
---|---|---|---|---|
A | Q | R | U | 3 |
A | Q | R | P | 2 |
A | Q | T | P | 2 |
A | Q | T | U | 2 |
B | Q | R | P | 2 |
C | Q | R | P | 2 |
C | Q | R | U | 2 |
C | Q | T | U | 2 |
B | Q | R | U | 1 |
B | Q | T | U | 1 |
C | Q | T | P | 1 |
这是表 2 的 Col_4 的正确数字 (ct)。我只需要匹配此输出中的列和表 1。我还可以GROUP BY
fewer 列来获得 Col_3、Col_2 的正确数字,和 1. 例如
SELECT
col_1,
col_2,
col_3,
COUNT() AS ct
FROM samptbl
GROUP BY
col_1,
col_2,
col_3
ORDER BY ct DESC;
Col_1 | Col_2 | Col_3 | ct |
---|---|---|---|
A | Q | R | 5 |
A | Q | T | 4 |
C | Q | R | 4 |
B | Q | R | 3 |
C | Q | T | 3 |
B | Q | T | 1 |
我现在在 SQLite 中执行此操作,但如果需要,我可以使用任何其他语言(PostgreSQL、Python)。如果可能的话,我真的希望这在 SQL 中是 100%。我正在使用的数据集很大,因此需要良好的效率。
【问题讨论】:
【参考方案1】:你可以用窗口函数COUNT()
:
SELECT ID,
COUNT(*) OVER (PARTITION BY Col_1) Col_1,
COUNT(*) OVER (PARTITION BY Col_1, Col_2) Col_2,
COUNT(*) OVER (PARTITION BY Col_1, Col_2, Col_3) Col_3,
COUNT(*) OVER (PARTITION BY Col_1, Col_2, Col_3, Col_4) Col_4
FROM table1
ORDER BY ID
无需任何更改,它也适用于 Postgresql。 请参阅demo。
【讨论】:
谢谢你,我试过这个,我运行了大约 150 秒。比我想象的要好!您对这种方法与 Turo 的效率有何见解。 (我会同时尝试并报告...) 如果 150 秒比您希望的要好,那么您必须有一个相当大的表。通常窗口函数比简单的聚合执行得更好。在您的情况下,您可以使用每种情况的索引来测试性能:Col_1、(Col_1、Col_2)、(Col_1、Col_2、Col_3)和(Col_1、Col_2、Col_3、Col_4)。【参考方案2】:您可以使用 CREATE TABLE AS 和简单的子选择:
CREATE TABLE TABLE2 AS
SELECT a.ID,
(SELECT COUNT(ID) FROM samptbl WHERE a.col_1 = col_1) as col_1,
(SELECT COUNT(ID) FROM samptbl WHERE a.col_1 = col_1 and a.col_2 = col_2) as col_2,
(SELECT COUNT(ID) FROM samptbl WHERE a.col_1 = col_1 and a.col_2 = col_2 and a.col_3 = col_3) as col_3,
(SELECT COUNT(ID) FROM samptbl WHERE a.col_1 = col_1 and a.col_2 = col_2 and a.col_3 = col_3 and a.col_4 = col_4) as col_4
FROM samptbl a;
db-fiddle
但是效率不会很好……
【讨论】:
非常感谢,这非常有用!这就是我脑海中的方向。我没有将它的性能与 forpas 的解决方案进行比较。以上是关于计算 SQL 表中关于列的相同记录的主要内容,如果未能解决你的问题,请参考以下文章