2017-10-17 7 views
1

j'ai une table de réponses avec le schéma suivant:Nombre cumulé sur les dates, en rejetant certaines valeurs

CREATE TABLE Answers 
    ([id] int, [analyst_id] int, [date] date); 

Je dois « accumuler-count » combien de réponses analyste a par mois, supprimant toutes les réponses données avant une période de 3 mois après la dernière réponse. Compte tenu de ce qui suit:

INSERT INTO Answers 
    ([id], [analyst_id], [date]) 
VALUES 
    (1, 1, '2017/01/01'), 
    (2, 1, '2017/02/01'), -- should be discarded 
    (3, 1, '2017/03/01'), -- should be discarded 
    (4, 1, '2017/05/01'), 
    (5, 1, '2017/06/01'), -- should be discarded 
    (6, 1, '2017/07/01'), -- should be discarded 
    (7, 1, '2017/08/01'), 
    (8, 2, '2017/01/01'), 
    (9, 2, '2017/04/01'), 
    (10, 1, '2018/02/01'), 
    (11, 2, '2018/03/01'); 

Le résultat attendu est:

analyst_id | month-year | count 
------------------------------- 
1   | 01/2017 | 1 
1   | 02/2017 | 1 
1   | 03/2017 | 1 
1   | 04/2017 | 1 
1   | 05/2017 | 2 
1   | 06/2017 | 2 
1   | 07/2017 | 2 
1   | 08/2017 | 3 
1   | 09/2017 | 3 
1   | 10/2017 | 3 
1   | 11/2017 | 3 
1   | 12/2017 | 3 
2   | 01/2017 | 1 
2   | 02/2017 | 1 
2   | 03/2017 | 1 
2   | 04/2017 | 2 
2   | 05/2017 | 2 
2   | 06/2017 | 2 
2   | 07/2017 | 2 
2   | 08/2017 | 2 
2   | 09/2017 | 2 
2   | 10/2017 | 2 
2   | 11/2017 | 2 
2   | 12/2017 | 2 
1   | 01/2018 | 0 
1   | 02/2018 | 1 
1   | 03/2018 | 1 
2   | 01/2018 | 0 
2   | 02/2018 | 0 
2   | 03/2018 | 1 

SGBD est un SQL Server 2012.

EDIT

J'ai écrit ce violon avec mon demi-courant solution: http://sqlfiddle.com/#!6/c2e82e/5

Chaque année, le compte doit être réinitialisé.

+2

La dernière réponse est en 2017-08. Je ne comprends pas pourquoi il est rejeté selon vos règles. –

+0

Mon mauvais. Mauvaise explication. Avant cette réponse (août), la dernière date acceptée était en juillet. La prochaine réponse acceptable sera en octobre. –

+1

quel problème rencontrez-vous dans votre requête? – Dinesh

Répondre

2

EDIT:

OK, pour la question mise à jour, vous devez essentiellement faire une table "dates" (ici un CTE appelé "D") qui contient toutes les dates entre le minimum et la date maximale votre table Réponses. Ensuite, vous pouvez essentiellement joindre vos résultats à cela et utiliser une fonction de fenêtre DENSE_RANK() pour déterminer le nombre.

DECLARE @Answers TABLE (ID INT, Analyst_ID INT, [Date] DATE); 
INSERT @Answers (ID, Analyst_ID, [Date]) 
VALUES 
    (1, 1, '2017/01/01'), 
    (2, 1, '2017/02/01'), 
    (3, 1, '2017/03/01'), 
    (4, 1, '2017/05/01'), 
    (5, 1, '2017/06/01'), 
    (6, 1, '2017/07/01'), 
    (7, 1, '2017/08/01'), 
    (8, 2, '2017/01/01'), 
    (9, 2, '2017/04/01'), 
    (10, 1, '2018/02/01'), 
    (11, 2, '2018/03/01'); 

WITH CTE AS 
(
    SELECT A.Analyst_ID, [Date] = MIN(A.[Date]) 
    FROM @Answers AS A 
    GROUP BY A.Analyst_ID 
    UNION ALL 
    SELECT A.Analyst_ID, A.[Date] 
    FROM 
    (
     SELECT A.Analyst_ID, A.[Date], RN = ROW_NUMBER() OVER (PARTITION BY A.Analyst_ID ORDER BY A.ID) 
     FROM @Answers AS A 
     JOIN CTE 
      ON CTE.Analyst_ID = A.Analyst_ID 
      AND DATEADD(MONTH, 3, CTE.[Date]) <= A.[Date] 
    ) AS A 
    WHERE A.RN = 1 
), 

D AS -- List of dates between minimum and maximum date in table for each analyst ID. 
(
    SELECT [Date] = DATEADD(MONTH, RN, (SELECT MIN([Date]) FROM @Answers)), 
      A.Analyst_ID 
    FROM (SELECT RN = ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) - 1 FROM sys.objects) AS O 
    CROSS JOIN (SELECT DISTINCT Analyst_ID FROM @Answers) AS A 
    WHERE RN <= (SELECT DATEDIFF(MONTH, MIN([Date]), MAX([Date])) FROM @Answers) 
) 

SELECT D.Analyst_ID, 
     [Month-Year] = FORMAT(D.[Date], 'MM/yyyy'), 
     [Count] = CASE WHEN A.[Date] IS NULL THEN 0 ELSE DENSE_RANK() OVER (PARTITION BY D.Analyst_ID, DATEPART(YEAR, A.[Date]) ORDER BY A.[Date]) END 
FROM D 
OUTER APPLY (SELECT TOP 1 * FROM CTE WHERE CTE.[Date] <= D.[Date] AND DATEDIFF(YEAR, CTE.[Date], D.[Date]) = 0 AND CTE.Analyst_ID = D.Analyst_ID ORDER BY CTE.[Date] DESC) AS A 
ORDER BY D.Analyst_ID, D.[Date]; 
+0

Je suis désolé ... encore une fois, ma mauvaise. Je pensais que c'était la bonne réponse, mais il est bon de sauter des mois, et dans ce cas, le mois suivant (n'importe quelle date après 3 mois) va juste augmenter de 1. Donc, si je n'ai que janvier et octobre avec des réponses, être 1, chaque mois après cela aura également 1, et puis octobre aura 2. –

+0

@JonathasCosta J'ai édité dans une réponse mise à jour basée sur ce que je pense que vous essayez d'atteindre. Essentiellement, quoi que vous fassiez, vous devrez combler les lacunes avec les dates, ce qui signifie créer une sorte de table de dates (pour chaque ID d'analyste). Après cela, le processus est le plus souvent le même qu'avant. Ici j'utilise DENSE_RANK() et la partition par année pour faire le compte. – ZLK