2016-09-27 2 views
0

У меня есть таблица Rep со следующими полями:TSQL - Выбор строки, в которых значение столбца изменилось

enter image description here

Там могут быть изменения в RepNbr. Мне нужно написать запрос, который показывает, что такое repnbr для каждого effectivedate. То, что было раньше, а затем, когда произошли изменения. Итак, я пытаюсь вытащить сообщение M258 на 10/21 (что было раньше), repmbr DM25 на 6/3/16 и то, что было в 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

Что я делаю не так с моим запросом? Спасибо,

+0

как должен результат выглядит? –

+0

'Я пытаюсь вытащить repnbr из M258 на 10/21' - я не нахожу ссылки на это в вашем коде – techspider

+0

все, что вы сделали, исключает одну строку данных ... и вы собираетесь хотите разбить Acct, EffectiveDate, чтобы вы получили по одной записи для каждой учетной записи за каждую эффективную дату. Поскольку ваши строки уникальны, все это кажется тривиальным. Возможно, ваш реальный набор данных продемонстрирует лучший пример. – scsimon

ответ

1

LAG() USE и или LEAD() функции для SQL 2012+

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') 

Затем он начнет с M258 с изменением 6/3 на DM25 на 10/15, а затем сменится на M258 на 10/21.

Если вы не хотите, чтобы увидеть оригинал/начальное значение просто удалить WHERE PrevRepNbr IS NULL

Edit без @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 
+0

Это будет работать, за исключением того, что у меня есть 600 000 + учетных записей, чтобы сделать Insert Into @Rep. Есть ли способ вытащить данные, не делая INSERT INTO? Я показываю только один пример. – BIReportGuy

+0

Да, просто замените FROM @Rep на FROM Tablename вашей исходной таблицы и не используйте переменную таблицы вообще – Matt

+0

@BIGuy, если мой ответ сработал для вас, подумайте о том, чтобы принять его, чтобы другие знали, что вы получили то, что вам нужно, и очки репутации назначены. Благодарю. http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work – Matt

1

Старые Sql разъединить версии группировки

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; 
+0

изменение обычно вступает в силу с минимальным значением EffectiveDate, но не согласуется с тем, что OP делает его другим по причине ожидаемых результатов и данных примера, выходящих из заказ. – Matt

+1

@matt, Sure OP может сортировать и выбирать min/max по мере необходимости. Спасибо за подсказку. – Serg