【问题标题】:SQL: retrieve only the records whose value has changed with first rowSQL:仅检索其值与第一行发生变化的记录
【发布时间】:2017-03-28 19:42:54
【问题描述】:

对不起,新手。

此处与此类似:SQL: retrieve only the records whose value has changed

我想知道如何也包括第一行?带 * 的行?

ID  description    eaudittimestamp
--  -----------    -----------------------
777012  above       2017-03-27 10:09:59.330 *
777012  above       2017-03-27 10:09:58.550
777012  below       2017-03-27 10:26:03.560 *
777012  below       2017-03-27 10:36:02.423
777012  below       2017-03-27 10:37:15.250
777012  middle      2017-03-27 10:49:11.680 *
777012  middle      2017-03-27 10:49:18.870
777013      something       2017-03-27 11:49:18.870
777013      something       2017-03-27 12:49:18.870
777014      nodescription   2017-03-27 12:49:18.870

抱歉,我是新手。让我改述一下。我有一个表,其中有 ID、描述和时间戳。类似于审计表。如何找到描述已更改的行(包括第一行)。

以及如何排除只有 1 行的那些?即 777013 和 777014?

【问题讨论】:

  • 您使用 like 作为速率并根据日期获得最大值或最小值,或者只是做前 1 个。
  • 现在搞混了。
  • 是的,抱歉,正在学习使用该网站。 :)

标签: sql sql-server-2008


【解决方案1】:
with ct as
(
    select Code, Date, Rate,
           row_number() over (partition by Code, Rate order by Code, Date) as rn
    from your_table
)
select Code, Date, Rate
from   ct
where  rn = 1
order by Code, Date;

更新

declare @foo table(ID int,  description varchar(100),  eaudittimestamp datetime);
insert into @foo values
(777012, 'above', '2017-03-27 10:09:59.330'),
(777012, 'above', '2017-03-27 10:09:58.550'),
(777012, 'below', '2017-03-27 10:26:03.560'),
(777012, 'below', '2017-03-27 10:36:02.423'),
(777012, 'below', '2017-03-27 10:37:15.250'),
(777012, 'middle', '2017-03-27 10:49:11.680'),
(777012, 'middle', '2017-03-27 10:49:18.870'),
(777013, 'something', '2017-03-27 11:49:18.870'),
(777013, 'something', '2017-03-27 12:49:18.870'),
(777014, 'nodescription', '2017-03-27 12:49:18.870');

with ct as
(
    select ID, description, eaudittimestamp,
           row_number() over (partition by ID, description order by eaudittimestamp) rn,
           count(*) over (partition by ID) as ct
    from   @foo
)
select ID, Description, eaudittimestamp
from ct
where rn = 1 and ct > 1;

GO
身份证 |说明 |审计时间戳 -----: | :------------ | :----------------- 777012 |以上 | 27/03/2017 10:09:58 777012 |下面 | 27/03/2017 10:26:03 777012 |中间 | 27/03/2017 10:49:11 777013 |东西| 27/03/2017 11:49:18

dbfiddle here

【讨论】:

    【解决方案2】:

    对于您提供的数据,row_number() 有效:

    select t.*
    from (select t.*,
                 row_number() over (partition by id, description order by eaudittimestamp) as seqnum
          from t
         ) t
    where seqnum = 1;
    

    这会为每个 id/description 对返回一行。 eaudittimestamp 最低的那个。这似乎是你想要的。

    编辑:

    如果要排除只有一行的组,只需使用另一个窗口函数:

    select t.*
    from (select t.*,
                 row_number() over (partition by id, description order by eaudittimestamp) as seqnum,
                 min(description) over (partition by id) as min_d,
                 max(description) over (partition by id) as max_d
          from t
         ) t
    where seqnum = 1 and min_d <> max_d;
    

    【讨论】:

    • 谢谢戈登。如果有倍数怎么办?我,e 它应该返回 3 行?
    • @Kayen 这是您查找row_number() 并开始尝试自己理解的部分。去SQL Fiddle玩吧;我为你创建了一个demo
    • 这可行,但会返回 seq =1 的所有行。如果我们只想找到有变化的行怎么办?
    • 抱歉不太清楚。我修复示例。使用 Gordon 的代码,777013 会显示为 seq = 1。如何使不包含?
    • @Kay_e_n 。 . .一种方法是count(distinct) over,但我认为这在 SQL Server 2008 中不起作用。您只需查看每个iddescription 的最小值和最大值,并确保它们不同。跨度>
    猜你喜欢
    • 2021-11-11
    • 2010-10-15
    • 1970-01-01
    • 1970-01-01
    • 2010-10-08
    • 2023-04-07
    • 1970-01-01
    • 1970-01-01
    • 2020-04-12
    相关资源
    最近更新 更多