我有一张名为test的表 在测试中,我有一个ID,一个值和一个日期 每个ID都会订购日期 我想在更改值之前和之后为ID选择行,因此以下示例表。
RowNum -------- ID -------值--------日期
1 ------------------ 001 --------- 1 ----------- 01/01/2015
2 ------------------ 001 --------- 1 ----------- 02/01/2015
3 ------------------ 001 --------- 1 ----------- 04/01/2015
4 ------------------ 001 --------- 1 ----------- 05/01/2015
5 ------------------ 001 --------- 1 ----------- 06/01/2015
6 ------------------ 001 --------- 1 ----------- 08/01/2015
7 ------------------ 001 --------- 0 ----------- 09/01/2015
8 ------------------ 001 --------- 0 ----------- 10/01/2015
9 ------------------ 001 --------- 0 ----------- 11/01/2015
10 ----------------- 001 --------- 1 ----------- 12/01/2015
11 ----------------- 001 --------- 1 ----------- 14/01/2015
12 ------------------ 002 --------- 1 ----------- 01/01/2015
13 ------------------ 002 --------- 1 ----------- 04/01/2015
14 ------------------ 002 --------- 0 ----------- 05/01/2015
15 ------------------ 002 --------- 0 ----------- 07/01/2015
结果将返回第6,7,9,10,13,14行
答案 0 :(得分:4)
您可以使用分析函数LAG()
和LEAD()
来访问前后行中的值,然后检查它是否与当前行中的值不匹配。
SELECT *
FROM (
SELECT RowNum,
ID,
Value,
Date,
LAG(VALUE, 1, VALUE) OVER(ORDER BY RowNum) PrevValue,
LEAD(VALUE, 1, VALUE) OVER(ORDER BY RowNum) NextValue
FROM test)
WHERE PrevValue <> Value
OR NextValue <> Value
传递给这个函数的参数是
LAG()
将返回第一行NULL
,而LEAD()
将返回NULL
作为最后一行,但它们在您的问题中看起来并不特别,所以我使用列值作为默认值。答案 1 :(得分:1)
请参阅以下内容,不使用LEAD和LAG:
DECLARE @i INT = 1,
@cnt INT,
@dstvalue INT,
@srcvalue INT
CREATE TABLE #result
(
id INT,
mydate DATE
)
CREATE TABLE #temp1
(
rn INT IDENTITY(1, 1),
id INT,
mydate DATE
)
INSERT INTO #temp1
(id,
mydate)
SELECT id,
mydate
FROM table
ORDER BY id,
mydate
SELECT @cnt = Count(*)
FROM #temp1
SELECT @srcvalue = value
FROM #temp1
WHERE rn = @i
WHILE ( @i <= @cnt )
BEGIN
SELECT @dstvalue = value
FROM #temp1
WHERE rn = @i
IF( @srcvalue = @dstvalue )
BEGIN
SET @i = @i + 1
CONTINUE;
END
ELSE
BEGIN
SET @srcvalue = @dstvalue
INSERT INTO #result
(id,
mydate)
SELECT id,
mydate
FROM #temp
WHERE rn = @i - 1
UNION ALL
SELECT id,
mydate
FROM #temp
WHERE rn = @i
END
SET @i = @i + 1
END
SELECT *
FROM #result
答案 2 :(得分:1)
使用lag()
和lead()
的答案是正确答案。如果您使用的是SQL Server 2012之前版本,那么您可以使用cross apply
或相关子查询执行相同的操作:
select t.*
from test t cross apply
(select top 1 tprev.*
from test tprev
where tprev.date < t.date
order by date desc
) tprev cross apply
(select top 1 tnext.*
from test tnext
where tnext.date > t.date
order by date asc
) tnext
where tprev.value <> tnext.value;