SQL - 通过两列聚合问题分组

Posted

技术标签:

【中文标题】SQL - 通过两列聚合问题分组【英文标题】:SQL - group by with two colums agregation problem 【发布时间】:2011-01-26 09:59:35 【问题描述】:

我今天的问题是我有一个包含这样行的表:

ID NAME NUMBER IDN
1  dsad 500600 12
1  dsad 600700 13
2  kkkk 111222 56
2  kkkk 333232 57

在一个 ID 示例 1 中,我有 2 个相同的名字、2 个不同的号码和不同的 IDN。

我想要的是为每个 ID 提取单行,其中 idn 值较小。 所以我想要这样的东西

1  dsad  500600 12
2  kkkk  111222 56

是否可以编写单个 sql 以获得该结果?我尝试按 ID 和 NAME 对其进行分组,并使用 min(IDN) 但我被数字字段卡住了:) 有什么想法吗?

【问题讨论】:

【参考方案1】:

你快到了,只需添加 MIN(Number) 字段。

SELECT  ID
        , NAME
        , MIN(NUMBER)
        , MIN(IDN)
FROM    ATable
GROUP BY
        ID
        , NAME

回应评论

以下将为您提供MIN(IDN) 的记录,无论该特定记录的编号是多少。

SELECT  t.*
FROM    ATable t
        INNER JOIN (        
          SELECT  ID, IDN = MIN(IDN)
          FROM    ATable
          GROUP BY ID
        ) tmin ON tmin.ID = t.ID
                  AND tmin.IDN = t.IDN

【讨论】:

我真的不能这样做,因为我不想要 NUMBER 中的 MIN 值,我不想要 MIN(IDN) 所在行中的值 @shin - 一个不幸的巧合,但在你的例子中它匹配,我误解了它。我添加了一个处理它的查询。 是的,它起作用了:D 我花了一段时间,因为我的 ATable 已经是一个很大的选择,加入:D 谢谢 m8 ;D @cyberkiwi,是的,但我认为我们可以假设 IDN 是唯一的。如果不是,添加 DISTINCT 就足够了。 这还不够。外部查询将显示同一 IDN 的 >1 条记录,而无需其他级别的查询【参考方案2】:
DECLARE @TABLE table (ID int, [NAME] varchar(100),NUMBER int ,IDN int)
insert into @TABLE SELECT 1,'dsad',500600,12
insert into @TABLE SELECT 1,'dsad',600700, 13
insert into @TABLE SELECT 2,'kkkk',111222, 56
insert into @TABLE SELECT 2,'kkkk',333232, 57

select t.ID, t.[Name], t.Number, t.IDN
from (
   select [NAME],min(IDN) as minIDN
   from @TABLE group by [NAME]
) as x inner join @TABLE as t on t.[Name]=x.[Name] and t.IDN = x.minIDN;

【讨论】:

+1 但这是 SQL Server 语法。我不认为测试脚本可以移植到 Oracle。【参考方案3】:

仅使用左连接且没有子查询的版本,带有 SQlite3 和 shell 脚本,因为我手头没有任何其他 ATM:

#!/bin/sh

rm -f test.sqlite
sqlite3 test.sqlite << AAA
CREATE TABLE test (id int, name text, number int, idn int);
INSERT INTO test VALUES(1,'dsad',500600,12);
INSERT INTO test VALUES(1,'dsad',600700,13);
INSERT INTO test VALUES(2,'kkkk',111222,56);
INSERT INTO test VALUES(2,'kkkk',333232,57);
INSERT INTO test VALUES(1,'dsad',600700,9);
INSERT INTO test VALUES(2,'kkkk',333232,59);
INSERT INTO test VALUES(2,'cccc',333232,59);
SELECT a.* FROM test a
    LEFT JOIN test b ON
            a.id=b.id AND
            a.name=b.name
            AND a.idn > b.idn
            WHERE b.id IS NULL;
AAA
# Result:
# 1|dsad|600700|9
# 2|cccc|333232|59
# 2|kkkk|111222|56

任何人都可以评论性能更好的地方吗?我认为这也很重要!

【讨论】:

在没有索引的情况下,在这一小组数据上,您的解决方案比我的解决方案快一倍。在 ID 上添加索引使这两种解决方案同样快。使用 60 条记录,我给出的解决方案(带索引)是这个的六倍。 请注意,我使用的是 SQL Server io Oracle。甲骨文的年限可能会有所不同。 +1。

以上是关于SQL - 通过两列聚合问题分组的主要内容,如果未能解决你的问题,请参考以下文章

分组并聚合具有两列值条件的数据框

Pandas Dataframe 中分组的多重聚合

如何对两列求和并通过减去它们的聚合 SQL 和 C# 在第三列中显示结果?

按 Sql Server 中的一列分组并按未包含在聚合函数或 GROUP BY 子句中的另一列排序

SQL - 使用 MAX 函数按问题分组两列

Postgres - 将两列聚合为一项