【问题标题】:Select row satisfying certain condition and rows next to it选择满足特定条件的行及其旁边的行
【发布时间】:2018-09-19 01:16:18
【问题描述】:

假设我有一个历史表记录谁修改了数据

-------------------------------------------------------------
|      ID      |  Last_Modif                  | User_Modif   | Col3, Col4...
-------------------------------------------------------------
|       1      |     2018-04-09 12:12:00      | John
|       2      |     2018-04-09 11:10:00      | Jim
|       3      |     2018-04-09 11:05:00      | Mary
|       4      |     2018-04-09 11:00:00      | John
|       5      |     2018-04-09 10:56:00      | David
|       6      |     2018-04-09 10:53:00      | John
|       7      |     2018-04-08 19:50:00      | Eric
|       8      |     2018-04-08 18:50:00      | Chris
|       9      |     2018-04-08 15:50:00      | John
|       10     |     2018-04-08 12:50:00      | Chris
----------------------------------------------------------

我想找到 John 所做的修改以及他之前的版本,以检查他修改了什么。例如在这种情况下,我想返回第 1、2、4、5、6、7、9、10 行

我正在考虑首先根据 Last_modif 进行排名,然后进行连接以获取下一行,但不知何故结果不正确。这似乎不是 LAG/LEAD 案例,因为我不是从下一行中选择单个值,而是整个下一行。有什么想法吗?

-- sample 1000 rows with RowNumber
with TopRows as
  (select top 1000 *, ROW_NUMBER() OVER(ORDER BY Last_modif desc) RowNum from [Table])
--Reference rows : Rows modif by John
  , ModifByJohn as
  (Select * from TopRows where USER_MODIF = 'John')

  select * from ModifByJohn
  UNION
  select ModifByNext.* from ModifByJohn join TopRows ModifbyNext on ModifByJohn.RowNum + 1 = ModifByNext.RowNum
  order by RowNum

如果我们想返回 John 之前的最后 2 个修改而不是 1,代码会是什么样子?

【问题讨论】:

  • 这个概念是可以的,但是在验证窗口函数的时候不要做TOP N,因为结果是不确定的。为什么你得到错误的结果?请记住,如果 John 可能修改了多条记录,那么您的起点 (ModifByJohn) 将有几个分散的行号。几个修改日期的行号也可能存在关联(您应该解开其他列,以便每次都能获得一致的结果)。
  • ID设置的顺序和Last_Modif一样吗?
  • @Pettrucci :好点。如果约翰有一连串的修改,你会建议什么修改,以便我们只采用一个约翰。例如John1, John2, Mary 将返回 J, J, M 而不是 J1, J2, J2, Mary ? @ McNets:没有相关性,这就是为什么我 ORDER BY Last_Modif 并在那里放一个 ROW_NUMBER

标签: sql-server lag rank row-number lead


【解决方案1】:

也许您可以利用您当前的 ID:

with x as
(
    select t1.*,
           (select top 1 id from tbl where id > t1.id) prev_id
    from  tbl t1
    where t1.User_Modif = 'John'
)
select * from x;
GO
身份证 |上次修改 |用户修改 | prev_id -: | :----------------- | :--------- | ------: 1 | 2018 年 9 月 4 日 12:12:00 |约翰 | 2 4 | 2018 年 9 月 4 日 11:00:00 |约翰 | 5 6 | 2018 年 9 月 4 日 10:53:00 |约翰 | 7 9 | 2018 年 8 月 4 日 15:50:00 |约翰 | 10
with x as
(
    select t1.*,
           (select top 1 id from tbl where id > t1.id) prev_id
    from  tbl t1
    where t1.User_Modif = 'John'
)
select ID, Last_Modif, User_Modif from x
union all 
select ID, Last_Modif, User_Modif 
from tbl
where  ID in (select prev_id from x)
order by ID
GO
身份证 |上次修改 |用户修改 -: | :----------------- | :--------- 1 | 2018 年 9 月 4 日 12:12:00 |约翰 2 | 2018 年 9 月 4 日 11:10:00 |吉姆 4 | 2018 年 9 月 4 日 11:00:00 |约翰 5 | 2018 年 9 月 4 日 10:56:00 |大卫 6 | 2018 年 9 月 4 日 10:53:00 |约翰 7 | 2018 年 8 月 4 日 19:50:00 |埃里克 9 | 2018 年 8 月 4 日 15:50:00 |约翰 10 | 2018 年 8 月 4 日 12:50:00 |克里斯

dbfiddle here

【讨论】:

    猜你喜欢
    • 2015-11-15
    • 2011-12-28
    • 2014-02-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-24
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多