如何根据特定的顺序选择每组的第一行?

Posted

技术标签:

【中文标题】如何根据特定的顺序选择每组的第一行?【英文标题】:How to select the top row of each group based on a specific ordering? 【发布时间】:2013-01-12 03:13:48 【问题描述】:

假设我有一个包含以下数据的表。

表名 [数据]。 PrimaryID:表的主 ID。 ParentID:表引用自身;这是对 PrimaryID 的 FK 约束。

DateTime:上次更新的时间。

PrimaryID        ParentID          Date
    1            null      1/1/2013
    2               1      1/2/2013
    3               1      1/3/2013
    4            null      1/4/2013
    5               4      1/5/2013
    6            null      1/6/2013

我想选择如下所示的结果:

PrimaryID        ParentID
        3               1
        5               4
        6               6

对于每个“组”(定义为具有相同 ParentID 和该父项的所有条目),我想选择最近的行,并替换一个空 ParentID(通常表示该行是parent) 具有行自己的 PrimaryID。

我真的不知道从哪里开始生成这样的查询。

我有一个看起来像这样的内部选择:

(SELECT PrimaryID, ISNULL(ParentID, PrimaryID) as ParentID, Date FROM [Data])

这看起来是正确的开始方向,但我不知道从哪里开始。

【问题讨论】:

【参考方案1】:

在@ypercube 的帮助下,这样的事情应该可以工作:

SELECT t.PrimaryId, coalesce(t.ParentId,t.PrimaryId) as parent
FROM YourTable t 
JOIN (
   SELECT coalesce(ParentId, PrimaryId) as parent, Max(DateField) as dtMax
   FROM YourTable
   GROUP BY coalesce(ParentId, PrimaryId)
) t2 ON coalesce(t.ParentId,t.PrimaryId) = parent AND t.DateField = t2.dtMax

这是更新后的Fiddle。

【讨论】:

这不会总是给出正确的结果:SQL-Fiddle test 您能否详细说明-您的小提琴中哪条记录不正确?我在 5 分钟前添加了 coalesce(t.ParentId,t.PrimaryId) (在回答之前没有在问题中看到)。谢谢。 6 已从结果中消失。 我认为你的 Fiddle 已经关闭——你的 4 有一个更高的日期:-) 您错过了重点,日期对组很重要(具有相同 parentId 的行)。看到这个:test-2【参考方案2】:

你可以使用row_number():

select primaryid,
  coalesce(ParentID, PrimaryID) parentid
from
(
  select *,
    row_number() over(partition by coalesce(ParentID, PrimaryID)
                      order by date desc) rn
  from yourtable
) src
where rn = 1

见SQL Fiddle with Demo

【讨论】:

以上是关于如何根据特定的顺序选择每组的第一行?的主要内容,如果未能解决你的问题,请参考以下文章

如何根据多个排序列选择每组的第一行?

如何选择每组的第一行?

如何获得每组的第一行?

如何将熊猫数据框值除以每组的第一行?

SQLite - 每个组的第一个 - 复合顺序和相反的排序顺序

从每组的第一行和最后一行获取值