【问题标题】:How to group this data so I can pull out specific rows from each group如何对这些数据进行分组,以便我可以从每个组中提取特定行
【发布时间】:2017-06-27 20:00:11
【问题描述】:

我有如下所示的数据集。由此,我想从PersonIDs 状态已更改为与前一个不同状态的每个组中选择第一行。

例如,从这个数据集中,我想要第 1、4、7 和 11 行。
有什么帮助吗?
如果我执行 GROUPBY,它只会将所有 New 和所有 Pending 归为 2 组。

PersonID    Status  WhenChanged
101         New     27/01/2017 15:27
101         New     27/01/2017 16:40
101         New     27/01/2017 16:40
101         Pending 27/01/2017 16:40
101         Pending 27/01/2017 16:40
101         Pending 27/01/2017 16:40
101         New     31/01/2017 09:14
101         New     31/01/2017 10:02
101         New     31/01/2017 10:03
101         New     31/01/2017 10:05
101         Pending 03/02/2017 14:29
101         Pending 03/02/2017 14:29

【问题讨论】:

    标签: sql sql-server-2008 group-by


    【解决方案1】:

    试一试...使用 CTE。订购已关闭,因为您使用的日期是 varchar 格式或显示为 varchar 格式。您可以将其转换为相同的,这将正常工作。

    declare @table table (PersonID int, Status varchar(16), WhenChanged varchar(64))
    insert into @table values
    (101,'New','27/01/2017 15:27'),
    (101,'New','27/01/2017 16:40'),
    (101,'New','27/01/2017 16:40'),
    (101,'Pending','27/01/2017 16:40'),
    (101,'Pending','27/01/2017 16:40'),
    (101,'Pending','27/01/2017 16:40'),
    (101,'New','31/01/2017 09:14'),
    (101,'New','31/01/2017 10:02'),
    (101,'New','31/01/2017 10:03'),
    (101,'New','31/01/2017 10:05'),
    (101,'Pending','03/02/2017 14:29'),
    (101,'Pending','03/02/2017 14:29')
    
    ;with cte as(
        select
            PersonID,
            Status,
            WhenChanged,
            case when lag(Status) over (partition by PersonID order by convert(datetime,WhenChanged,103)) <> Status then 1 else 0 end as d
        from
            @table)
    
    
    
    select top 1 *
    from @table
    union 
    select  PersonID,
            Status,
            WhenChanged
    from cte
    where d=1
    order by WhenChanged
    

    SQL Server 2008 及以前的版本

    declare @table table (PersonID int, Status varchar(16), WhenChanged varchar(64))
    insert into @table values
    (101,'New','27/01/2017 15:27'),
    (101,'New','27/01/2017 16:40'),
    (101,'New','27/01/2017 16:40'),
    (101,'Pending','27/01/2017 16:40'),
    (101,'Pending','27/01/2017 16:40'),
    (101,'Pending','27/01/2017 16:40'),
    (101,'New','31/01/2017 09:14'),
    (101,'New','31/01/2017 10:02'),
    (101,'New','31/01/2017 10:03'),
    (101,'New','31/01/2017 10:05'),
    (101,'Pending','03/02/2017 14:29'),
    (101,'Pending','03/02/2017 14:29')
    
    
    ;with cte as(
        select 
            PersonID,
            Status,
            convert(datetime,WhenChanged,103) as WhenChanged,
            row_number() over (order by personID, convert(datetime,WhenChanged,103)) as RN
        from
            @table),
    
    cteResults as(
        select
            PersonID,
            Status,
            WhenChanged
        from
            cte 
        where RN = 1
        UNION
        select
            c.PersonID,
            c.Status,
            c.WhenChanged 
        from
            cte c
        inner join
            cte c2 on c2.rn = (c.rn -1) and c2.status <> c.status)
    
    select * from cteResults order by WhenChanged
    

    【讨论】:

    • 非常感谢。不幸的是,当我尝试运行它时,我意识到我只有 sql server 2008,并且 lag 功能不起作用。有没有其他方法可以不延迟地写这个?
    • @Tan 我对 2016 年之前的帖子进行了编辑。请注意,您标记了 SQL Server 2016,这就是我使用 LAG() 的原因。确保下次标记正确的版本。我已更改您的问题以反映正确的标签。
    猜你喜欢
    • 2018-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-11
    • 1970-01-01
    • 1970-01-01
    • 2022-01-25
    相关资源
    最近更新 更多