Microsoft T-SQL считает последовательные записи - PullRequest
4 голосов
/ 07 мая 2010

Проблема: Начиная с самого последнего дня на человека, подсчитайте количество последовательных дней, в течение которых каждый человек получил 0 баллов за хорошее.

Пример данных для работы с:

Date       Name Points
2010-05-07 Jane 0  
2010-05-06 Jane 1  
2010-05-07 John 0  
2010-05-06 John 0  
2010-05-05 John 0  
2010-05-04 John 0  
2010-05-03 John 1  
2010-05-02 John 1  
2010-05-01 John 0

Ожидаемый ответ:

Джейн была плохой 5/7, но хорошей накануне. Так что совсем недавно Джейн была плохой 1 день подряд. Джон был плох в 5/7, снова в 5/6, 5/5 и 5/4. Он был хорош 5/3. Так что Джон был плохим последние 4 дня подряд.

Код для создания примера данных:

IF OBJECT_ID('tempdb..#z') IS NOT NULL BEGIN DROP TABLE #z END
select getdate() as Date,'John' as Name,0 as Points into #z 
insert into #z values(getdate()-1,'John',0)
insert into #z values(getdate()-2,'John',0)
insert into #z values(getdate()-3,'John',0)
insert into #z values(getdate()-4,'John',1)
insert into #z values(getdate(),'Jane',0)
insert into #z values(getdate()-1,'Jane',1)
select * from #z order by name,date desc

Во-первых, я извиняюсь, но новичок в этой системе и не могу понять, как работает интерфейс и правильно публиковать сообщения.

2010-05-13 ------------------------------------------ ---------------------------------
Джоэл, Большое спасибо за ваш ответ ниже! Мне это нужно для ключевой производственной работы, которая выполнялась около 60 минут.
Теперь работа выполняется за 2 минуты !!

Да, в моем случае было 1 условие, которое мне нужно было решить. Мой источник всегда имел записи только для тех, кто имел было плохо в последнее время, так что это не проблема для меня. Однако мне приходилось обрабатывать записи там, где они никогда не были хорошими, и сделал это с левым соединением, чтобы добавить обратно в записи и назначил им дату, чтобы подсчет сработал для всех.

Еще раз спасибо за вашу помощь. Это открыло мне немного больше для логики, основанной на SET, и того, как подойти ОГРОМНАЯ выгода для моей производственной работы.

1 Ответ

8 голосов
/ 07 мая 2010

Основное решение здесь состоит в том, чтобы сначала создать набор, который содержит имя каждого человека и значение последнего дня, в который этот человек был хорош.Затем объедините этот набор с исходной таблицей и сгруппируйте по имени, чтобы найти количество дней> последнего хорошего дня для каждого человека.Вы можете построить набор в CTE, представлении или некоррелированной производной таблице (подзапросе) - любой из них будет работать.В моем примере ниже используется CTE.

Обратите внимание, что, хотя концепция обоснована, этот конкретный пример может не вернуть точно того, что вы хотите.Ваши реальные потребности здесь зависят от того, что вы хотите, чтобы произошло с теми, кто никогда не был хорошим, и с теми, кто не был плохим в последнее время (то есть, вам может потребоваться левое соединение, чтобы показать пользователей, которые были хорошими вчера).Но это должно помочь вам начать:

WITH LastGoodDays AS
(
  SELECT MAX([date]) as [date], name
  FROM [table]
  WHERE Points > 0
  GROUP BY name
)
SELECT t.name, count(*) As ConsecutiveBadDays
FROM [table] t
INNER JOIN LastGoodDays lgd ON lgd.name = t.name AND t.[date] > lgd.[date]
group by t.name
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...