哇,這是一個真正的謎。我相信這有各種各樣的漏洞,但這裏有一個可能的解決方案。首先我們的測試數據:
If Exists(Select 1 From INFORMATION_SCHEMA.TABLES Where TABLE_NAME = 'recs')
DROP TABLE recs
GO
Create Table recs
(
Id int not null
, EmployeeId int not null
)
Insert recs(Id, EmployeeId)
Values (1,1) ,(2,1) ,(3,1) ,(4,2) ,(5,5) ,(6,1) ,(7,1) ,(8,1) ,(10,1)
,(11,1) ,(12,1) ,(13,2) ,(14,2) ,(15,2) ,(16,2)
接下來,您將需要一個包含數字序列的Tally或Numbers表。我只在這個中放了500個元素,但考慮到您可能需要更多的數據大小。 Tally表中最大的數字應該大於recs表中的最大數字。
Create Table dbo.Tally(Num int not null)
GO
;With Numbers As
(
Select ROW_NUMBER() OVER (ORDER BY s1.object_id) As Num
From sys.columns as s1
)
Insert dbo.Tally(Num)
Select Num
From Numbers
Where Num < 500
現在爲實際的解決方案。基本上,我用一系列CTE來推斷連續序列的開始和結束點。
; With
Employees As
(
Select Distinct EmployeeId
From dbo.Recs
)
, SequenceGaps As
(
Select E.EmployeeId, T.Num, R1.Id
From dbo.Tally As T
Cross Join Employees As E
Left Join dbo.recs As R1
On R1.EmployeeId = E.EmployeeId
And R1.Id = T.Num
Where T.Num <= (
Select Max(R3.Id)
From dbo.Recs As R3
Where R3.EmployeeId = E.EmployeeId
)
)
, EndIds As
(
Select S.EmployeeId
, Case When S1.Id Is Null Then S.Id End As [End]
From SequenceGaps As S
Join SequenceGaps As S1
On S1.EmployeeId = S.EmployeeId
And S1.Num = (S.Num + 1)
Where S.Id Is Not Null
And S1.Id Is Null
Union All
Select S.EmployeeId, Max(Id)
From SequenceGaps As S
Where S.Id Is Not Null
Group By S.EmployeeId
)
, SequencedEndIds As
(
Select EmployeeId, [End]
, ROW_NUMBER() OVER (PARTITION BY EmployeeId ORDER BY [End]) As SequenceNum
From EndIds
)
, StartIds As
(
Select S.EmployeeId
, Case When S1.Id Is Null Then S.Id End As [Start]
From SequenceGaps As S
Join SequenceGaps As S1
On S1.EmployeeId = S.EmployeeId
And S1.Num = (S.Num - 1)
Where S.Id Is Not Null
And S1.Id Is Null
Union All
Select S.EmployeeId, 1
From SequenceGaps As S
Where S.Id = 1
)
, SequencedStartIds As
(
Select EmployeeId, [Start]
, ROW_NUMBER() OVER (PARTITION BY EmployeeId ORDER BY [Start]) As SequenceNum
From StartIds
)
, SequenceRanges As
(
Select S1.EmployeeId, Start, [End]
From SequencedStartIds As S1
Join SequencedEndIds As S2
On S2.EmployeeId = S1.EmployeeId
And S2.SequenceNum = S1.SequenceNum
)
Select *
From SequenceGaps As SG
Where Exists(
Select 1
From SequenceRanges As SR
Where SR.EmployeeId = SG.EmployeeId
And SG.Id Between SR.Start And SR.[End]
And (SR.[End] - SR.[Start] + 1) >= @SequenceSize
)
WHERE子句和@SequenceSize在使用最後陳述時,你可以控制哪些返回序列。
這是第一步,但我仍然需要獲得至少有5個連續ID的數據塊。您的解決方案將獲取所有連續的行。 – Anax 2010-02-23 00:47:40