2010-05-07 4 views
4

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

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

 
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 ----------------------------------------- ----------------------------------
Joel, Большое вам спасибо за ваш ответ ниже! Мне нужно это для ключевой производственной работы, которая длилась около 60 минут.
Теперь работа проходит через 2 минуты!

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

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

+2

Мы не делаем домашнее задание здесь, не видя в нем первую часть работы. Даже если это не домашнее задание, мы хотели бы видеть, что работа в нем до сих пор. – Oded

+1

Пока вы предлагаете «ожидаемый ответ», мне нужно будет более конкретным образом определить, каким будет ожидаемый набор результатов. – Lucero

+3

+1, для «кода для создания данных образца», пожелайте, чтобы все это сделали! –

ответ

8

Основным решением здесь является создание набора, который содержит имя каждого человека и значение последнего дня, когда это лицо было хорошим. Затем присоедините этот набор к исходной таблице и группе по имени, чтобы найти количество дней> последнего хорошего дня для каждого человека. Вы можете построить набор в CTE, представлении или некоррелированной производной таблице (sub query) — любой из них будет работать. В моем примере ниже используется 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 
+0

+1 работает над моей системой. вы можете переместить CTE в производную таблицу, если используете SQL Server ниже версии 2005. –

Смежные вопросы