SQL 查询每个组 ID 仅返回 1 条记录

Posted

技术标签:

【中文标题】SQL 查询每个组 ID 仅返回 1 条记录【英文标题】:SQL query to return only 1 record per group ID 【发布时间】:2009-12-23 17:31:15 【问题描述】:

我正在寻找一种方法来处理以下情况。我有一个数据库表,我只需要为表中包含的每个“组 id”返回一条记录,此外,在每个组中选择的记录应该是家庭中最年长的人。

ID   Group ID   Name               Age
1   134        John Bowers        37
2   134        Kerri Bowers       33
3   135        John Bowers        44
4   135        Shannon Bowers     42

因此,在上面提供的示例数据中,我需要返回 ID 1 和 3,因为它们是每个组 ID 中最年长的人。

这是针对 SQL Server 2005 数据库查询的。

【问题讨论】:

如果你想要名字,如果你有>1个年龄最大的人,你仍然有机会选择>1行。在这种情况下,您还应该建立选择名称的标准。 好点克里斯。是想稍微简化一下这个问题,但这留下了这样的漏洞 :-) 我实际上还有另一个性别领域,所以我希望选择一个家庭中最年长的男性。如果有男性,那么最年长的女性。如果同一家庭中有两个年龄相同的男性,那么我只需要选择其中一条记录。这可以基于一些简单的事情,比如在决胜局中拥有最低 ID 号的人。 Joe Celko 的优秀著作“Smarties 的 SQL”的第 21.4 节“极值函数”对这类问题进行了很好的讨论。如果您遇到比简单的 SELECT 和 INSERT 更棘手的问题,我强烈推荐这本书。 【参考方案1】:
SELECT  t.*
FROM    (
        SELECT  DISTINCT groupid
        FROM    mytable
        ) mo
CROSS APPLY
        (
        SELECT  TOP 1 *
        FROM    mytable mi
        WHERE   mi.groupid = mo.groupid
        ORDER BY
                age DESC
        ) t

或者这个:

SELECT  *
FROM    (
        SELECT  *, ROW_NUMBER() OVER (PARTITION BY groupid ORDER BY age DESC) rn
        FROM    mytable
        ) x
WHERE   x.rn = 1

即使在平局的情况下,每组最多返回一条记录。

有关两种方法的性能比较,请参阅我的博客中的这篇文章:

SQL Server: Selecting records holding group-wise maximum

【讨论】:

+1:是的,忘了我关于关系的免责声明。忙于灭火。 谢谢夸斯诺伊。我能够将性别列添加到您的 ORDER By 子句中的年龄列中,并获得我正在寻找的结果! (在我最初的问题之后,仅在评论中讨论了性别专栏)您的解决方案是完美的,适应性强! 跟进问题。这些将针对 1.75 亿条记录运行。一个或另一个查询更有效吗? @Richard West: 你有多少个不同的组?你有一个单独的表格来包含这些组吗? 由于某种原因,SQL Server 给了我Msg 156, Level 15, State 1, Line 7 Incorrect syntax near the keyword 'WHERE'【参考方案2】:

用途:

SELECT DISTINCT
       t.groupid,
       t.name
  FROM TABLE t
  JOIN (SELECT t.groupid,
               MAX(t.age) 'max_age'
          FROM TABLE t
      GROUP BY t.groupid) x ON x.groupid = t.groupid
                           AND x.max_age = t.age

如果一个组有 2 个以上的同龄人怎么办?最好存储生日而不是年龄 - 您始终可以计算年龄以进行演示。

【讨论】:

【参考方案3】:

试试这个(假设 GroupHousehold 的同义词)

Select * From Table t
Where Age = (Select Max(Age)
             From Table 
             Where GroupId = t.GroupId)

如果某个家庭中有两个或更多“最年长”的人(他们的年龄相同,并且没有其他人年长),那么这将返回所有这些人,而不是随机返回一个。

如果这是一个问题,那么您需要添加另一个子查询来为该集合中的一个人返回任意键值。

Select * From Table t
Where Id = 
  (Select Max(Id) Fom Table 
   Where GroupId = t.GroupId
      And Age =
         (Select(Max(Age) From Table
          Where GroupId = t.GroupId))

【讨论】:

【参考方案4】:
SELECT GroupID, Name, Age
FROM table
INNER JOIN
(
SELECT GroupID, MAX(Age) AS OLDEST
FROM table
) AS OLDESTPEOPLE
ON
table.GroupID = OLDESTPEOPLE.GroupID
AND
table.Age = OLDESTPEOPLE.OLDEST

【讨论】:

以上是关于SQL 查询每个组 ID 仅返回 1 条记录的主要内容,如果未能解决你的问题,请参考以下文章

SQL 查询 - 返回连接表的前两条记录的连接

仅返回基于多连接中的一列的最小记录

MySQL:如何在 SQL 查询中为每个结果插入一条记录?

SQL查询:返回组的最大值记录

oracle 我有1000条查询语句,通过执行每一条sql语句,返回所有的查询结果为空的记录,能实现吗?

在一个查询中返回多个组中的前“X”条记录