2010-05-07 17 views
4

Problème: Depuis le dernier jour par personne, comptez le nombre de jours consécutifs pendant lesquels chaque personne a reçu 0 point pour être bonne.Microsoft T-SQL Comptage des enregistrements consécutifs

Exemple de données pour travailler à partir de:

 
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 

Réponse attendue:

Jane était mauvaise sur mais bon le 5/7 jours avant. Donc, Jane était seulement mauvaise 1 jour de suite plus récemment. John était mauvais sur 5/7, encore sur 5/6, 5/5 et 5/4. Il était bon le 5/3. Donc John était mauvais les 4 derniers jours d'affilée.

code pour créer des échantillons de données:

 
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 

Tout d'abord, je suis désolé, mais de nouveau à ce système et de la difficulté à comprendre comment fonctionne l'interface et afficher correctement.

2010-05-13 ----------------------------------------- ----------------------------------
Joel, Merci beaucoup pour votre réponse ci-dessous! J'en ai besoin pour un travail de production clé qui durait environ 60 minutes.
Maintenant, le travail s'exécute en 2 minutes !!

Oui, il y avait 1 condition dans mon cas que je devais adresser. Ma source n'a toujours eu qu'un record pour ceux qui avaient été mal récemment, donc ce n'était pas un problème pour moi. J'ai cependant dû gérer des disques où ils n'étaient jamais bons, et je l'ai fait avec une jointure à gauche pour rajouter dans les enregistrements et leur donner une date pour que le comptage fonctionne pour tous.

Merci encore pour votre aide. Il m'a ouvert un peu plus l'esprit à la logique basée sur SET et comment l'aborder et a été un énorme avantage pour mon travail de production.

+2

Nous ne faisons pas nos devoirs ici sans voir une partie du travail mis en avant. Même si ce n'est pas un devoir, nous aimerions que le travail soit fait jusqu'à maintenant. – Oded

+1

Alors que vous fournissez une "réponse attendue", je devrais voir de façon plus concrète ce que l'ensemble de résultats attendu serait. – Lucero

+3

+1, pour 'Code pour créer des données d'échantillon', souhaite que tout le monde le fasse! –

Répondre

8

La solution de base ici est de construire d'abord un ensemble qui contient le nom de chaque personne et la valeur du dernier jour où cette personne était bonne. Ensuite, joignez cet ensemble à la table d'origine et regroupez par nom pour trouver le nombre de jours> le dernier bon jour pour chaque personne. Vous pouvez construire l'ensemble dans un CTE, une vue, ou une table dérivée non corrélée (sous-requête) — l'un de ceux qui fonctionnera. Mon exemple ci-dessous utilise un CTE. Notez que bien que le concept soit sain, cet exemple spécifique peut ne pas renvoyer exactement ce que vous voulez. Vos besoins réels ici dépendent de ce que vous voulez arriver pour ceux qui n'ont pas été bons et pour ceux qui n'ont pas été mauvais récemment (par exemple, vous pourriez avoir besoin d'une jointure gauche pour montrer aux utilisateurs qui étaient bons hier). Mais cela devrait vous aider à démarrer:

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 fonctionne sur mon système. vous pouvez déplacer le CTE dans une table dérivée si vous utilisez SQL Server en dessous de la version 2005. –

Questions connexes