TSQL - 选择列值已更改的行

时间:2016-09-27 18:01:20

标签: sql sql-server tsql

我有一个包含以下字段的Rep表:

enter image description here

RepNbr可能会有变化。我需要编写一个查询,显示每个有效日期的repnbr。什么是repnbr先前和当有变化时。所以,我试图在10月21日拉动M258的复制品(什么是repnbr先前),6月3日16日DM25的复制品以及M258的复制品是在6/8/16。

我尝试了以下查询:此查询仅提取6/3和6/8的有效日期,并且不会回顾之前的repnbr。

    ;with t1 as
(
select 
     acctnbr, 
     repnbr, 
     effectivedate,
     rn = row_number() over (partition by repnbr order by acctnbr)
from 
     reptable
where 
     acctnbr = '123'
)
select 
     *
from 
     t1
where  
     rn = '1'
order by 
     effectivedate

结果:

enter image description here

我的输出应该如下:

enter image description here

我的查询错误是什么? 谢谢,

2 个答案:

答案 0 :(得分:2)

用于SQL 2012 +

的USE LAG()和/或LEAD()函数
DECLARE @Rep AS TABLE (Acct INt, RepNbr CHAR(4), EffectiveDate DATETIME)
INSERT INTO @Rep VALUES
(123,'M258','2015-10-15')
,(123,'M258','2015-10-21')
,(123,'DM25','2015-06-03')
,(123,'M258','2015-06-08')

;WITH cte AS (
    SELECT *
       ,LAG(RepNbr) OVER (PARTITION BY Acct ORDER BY EffectiveDate) as PrevRepNbr
    FROM
       @Rep
)

SELECT Acct, RepNbr, EffectiveDate
FROM
    cte 
WHERE
    PrevRepNbr IS NULL
    OR PrevRepNbr <> RepNbr

请注意,您的示例不是生效日期的顺序,因此您的结果将不会如您所述。因为10-21是在6-3之后......

Acct    RepNbr  EffectiveDate
123     DM25    2015-06-03 00:00:00.000
123     M258    2015-06-08 00:00:00.000
123     M258    2015-10-15 00:00:00.000
123     M258    2015-10-21 00:00:00.000

这意味着RepNbr仅在6/8从DM25变为M258

如果您将示例表更改为:

DECLARE @Rep AS TABLE (Acct INt, RepNbr CHAR(4), EffectiveDate DATETIME)
INSERT INTO @Rep VALUES
(123,'M258','2015-06-03')
,(123,'M258','2015-06-08')
,(123,'DM25','2015-10-15')
,(123,'M258','2015-10-21')

然后它开始于10月15日6/3更改为DM25的M258,然后在10月21日更改回M258。

如果您不想查看原始/起始值,请删除WHERE PrevRepNbr IS NULL

不使用@Rep进行编辑:

;WITH cte AS (
    SELECT
       Acct
       ,RepNbr
       ,EffectiveDate
       ,LAG(RepNbr) OVER (PARTITION BY Acct ORDER BY EffectiveDate) as PrevRepNbr
    FROM
       TableName
)

SELECT Acct, RepNbr, EffectiveDate
FROM
    cte 
WHERE
    PrevRepNbr IS NULL
    OR PrevRepNbr <> RepNbr

答案 1 :(得分:2)

较旧的Sql sever版本分组

DECLARE @Rep AS TABLE (Acctnbr int, RepNbr CHAR(4), EffectiveDate DATETIME)
INSERT INTO @Rep VALUES
(123,'M258','2015-10-15')
,(123,'M258','2015-10-21')
,(123,'DM25','2015-06-08')
,(123,'M258','2015-06-03');

WITH cte AS (
  select *, 
   grp = row_number() over(partition by acctnbr order by effectivedate)
   - row_number() over(partition  by acctnbr, RepNbr  order by effectivedate)
     from @rep
)
SELECT acctnbr, RepNbr, max(effectivedate) effectivedate
from cte
group by acctnbr, RepNbr, grp
order by acctnbr, max(effectivedate) desc;