【问题标题】:Find missing record and return adjacent records SQL查找缺失记录并返回相邻记录 SQL
【发布时间】:2017-09-29 19:49:17
【问题描述】:

我需要在原生 SQL 中将相邻记录返回到序列中的缺失记录。如果序列中的第一个条目丢失,则仅返回下一个条目。无需在序列中寻找缺失的一端。

这是在 SQL Server 12.0.2000.8 中运行的

相关列的结构:

BatchId(nvarchar(50), null) 
CreateDate(datetime, null)
UserId(varchar(50), null) 
Batch(varchar(50), null)

“-”之后的 BatchId 中的最后一个数字确定顺序。 BatchId 与批次相关。当批次更改时,BatchId 上的序列应重置为 1。

BatchId         CreateDate              UserId      Batch
#########################################################
9K182855 - 1    2017-09-26 17:57:20.977 9K182855    8
9K182855 - 2    2017-09-26 18:20:57.693 9K182855    8
9K182855 - 1    2017-09-27 11:04:46.177 9K182855    9
9K182855 - 2    2017-09-27 11:19:32.990 9K182855    9

我用来获取数据的查询

select BatchID, CreateDate, UserId, Batch from Results
where CreateDate > dateadd(day,-2,getdate())
and Batch between 0 and 9
order by UserId, CreateDate, Batch;

这是数据

BatchId         CreateDate              UserId      Batch
#########################################################
4L182855 - 1    2017-09-28 14:04:46.177 4L182855    9
4L182855 - 2    2017-09-28 15:19:32.990 4L182855    9
4L182855 - 3    2017-09-28 16:30:27.953 4L182855    9
4L182855 - 4    2017-09-28 17:57:20.977 4L182855    9
4L182855 - 5    2017-09-28 18:20:57.693 4L182855    9
4L182855 - 1    2017-09-29 11:04:46.177 4L182855    0
4L182855 - 2    2017-09-29 11:19:32.990 4L182855    0
4L182855 - 3    2017-09-29 11:30:27.953 4L182855    0
4L182855 - 4    2017-09-29 11:57:20.977 4L182855    0
4L182855 - 5    2017-09-29 12:00:57.693 4L182855    0
4L182855 - 6    2017-09-29 12:04:46.177 4L182855    0
4L182855 - 7    2017-09-29 12:19:32.990 4L182855    0
4L182855 - 8    2017-09-29 12:30:27.953 4L182855    0
4L182855 - 9    2017-09-29 13:57:20.977 4L182855    0
4L182855 - 10   2017-09-29 14:20:57.693 4L182855    0

这是缺少数据

BatchId         CreateDate              UserId      Batch
#########################################################
4L182855 - 1    2017-09-28 14:04:46.177 4L182855    9
4L182855 - 2    2017-09-28 15:19:32.990 4L182855    9
4L182855 - 4    2017-09-28 17:57:20.977 4L182855    9
4L182855 - 5    2017-09-28 18:20:57.693 4L182855    9
4L182855 - 1    2017-09-29 11:04:46.177 4L182855    0
4L182855 - 2    2017-09-29 11:19:32.990 4L182855    0
4L182855 - 3    2017-09-29 11:30:27.953 4L182855    0
4L182855 - 4    2017-09-29 11:57:20.977 4L182855    0
4L182855 - 5    2017-09-29 12:00:57.693 4L182855    0
4L182855 - 6    2017-09-29 12:04:46.177 4L182855    0
4L182855 - 7    2017-09-29 12:19:32.990 4L182855    0
4L182855 - 8    2017-09-29 12:30:27.953 4L182855    0
4L182855 - 10   2017-09-29 14:20:57.693 4L182855    0

要求是返回下面的行,它们与丢失的记录相邻

BatchId         CreateDate              UserId      Batch
#########################################################
4L182855 - 2    2017-09-28 15:19:32.990 4L182855    9
4L182855 - 4    2017-09-28 17:57:20.977 4L182855    9
4L182855 - 8    2017-09-29 12:30:27.953 4L182855    0
4L182855 - 10   2017-09-29 14:20:57.693 4L182855    0

我可以在 Python 中或可能通过 CLR 用户定义函数来执行此操作。但是,我不确定它在本机 SQL 中是否可行。如果可以,请赐教。

【问题讨论】:

  • 缺失的行是否由BatchId确定?
  • 当批次的第一行丢失时,您将如何处理?您能否确定批次的最后一行丢失的情况?
  • 是的,先生,BatchId 中“ - ”之后的最后一个数字。 BatchId 应始终与 Batch 相关联。当批次从 9 变为 0 时,BatchId 上的计数器应重置为 1。UserId 可以不同。我将更改问题以反映您的评论。谢谢
  • 您的数据中存在近乎重复的内容。例如,BatchId 后缀为“1”的两行具有完全相同的BatchId。这些行仅由CreateDate 不同。但是 CreateDate 对于您显示的顺序中的连续行不同。因此,没有一列或一组列将第一个五个值的序列与第二个 10 个值的集合区分开来。然而,必须区分这些序列以确定每个序列是否包含间隙。
  • 在 SQL 中完全可行。我会把一些东西放在一起,但我不确定它会运行多快。

标签: sql sql-server


【解决方案1】:

使用stuff() 截断batchid 以获取批处理序列,并使用lead()lag() 从计算BatchSeq 的上一行和下一行中获取值:

select s.BatchId, s.CreateDate, s.UserId, s.Batch
from (
  select t.*
    , PrevSeq = lag(x.BatchSeq)  over (partition by Batch order by CreateDate)
    , x.BatchSeq
    , NextSeq = lead(x.BatchSeq) over (order by CreateDate)
  from results t
    cross apply (values (convert(int,stuff(t.batchid,1,charindex('- ',t.batchid)+1,'')))
      ) x (BatchSeq)
  ) s
where BatchSeq - isnull(PrevSeq,0) != 1 
  or (BatchSeq - NextSeq !=-1 and NextSeq != 1)
order by createdate

rextester 演示:http://rextester.com/ZCBLP37968

返回:

+---------------+---------------------+----------+-------+
|    BatchId    |     CreateDate      |  UserId  | Batch |
+---------------+---------------------+----------+-------+
| 4L182855 - 2  | 2017-09-28 15:19:32 | 4L182855 |     9 |
| 4L182855 - 4  | 2017-09-28 17:57:20 | 4L182855 |     9 |
| 4L182855 - 8  | 2017-09-29 12:30:27 | 4L182855 |     0 |
| 4L182855 - 10 | 2017-09-29 14:20:57 | 4L182855 |     0 |
+---------------+---------------------+----------+-------+

这也适用于缺少第一条记录:http://rextester.com/BLAD55913

【讨论】:

  • 先生,您抽签很快。 where 子句也很不错。比我想出的更有效率。非常好。
  • 非常令人印象深刻,考虑到我的想法。谢谢楼主
  • @rreeves 乐于助人!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-31
  • 2020-03-15
  • 2017-05-05
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多