2010-09-14 8 views
3

Je cherche des informations de reclasser relativement simple de la manière la plus efficace possible: En utilisant une sélection limitée de l'échantillon des données:sql définir une ligne par le nombre de fois/comment il apparaît que d'autres lignes

CREATE TABLE #data 
(id varchar(30) 
,payent_type varchar(30) 
,payment_date DATETIME) 

INSERT INTO #data values ('001','single gift',DATEADD(MM,-12,GETDATE())) 
INSERT INTO #data values ('001','regular gift',DATEADD(MM,-39,GETDATE())) 
INSERT INTO #data values ('002','regular gift',DATEADD(MM,-06,GETDATE())) 
INSERT INTO #data values ('003','single gift',DATEADD(MM,-96,GETDATE())) 
INSERT INTO #data values ('003','regular gift',DATEADD(MM,-96,GETDATE())) 
INSERT INTO #data values ('003','single gift',DATEADD(MM,-1,GETDATE())) 
INSERT INTO #data values ('004','single gift',DATEADD(MM,-54,GETDATE())) 
INSERT INTO #data values ('005','regular gift',DATEADD(MM,-2,GETDATE())) 
INSERT INTO #data values ('005','regular gift',DATEADD(MM,-8,GETDATE())) 
INSERT INTO #data values ('006','single gift',DATEADD(MM,-12,GETDATE())) 
INSERT INTO #data values ('007','regular gift',DATEADD(MM,-2,GETDATE())) 
INSERT INTO #data values ('007','regular gift',DATEADD(MM,-6,GETDATE())) 
INSERT INTO #data values ('008','single gift',DATEADD(MM,-1,GETDATE())) 
INSERT INTO #data values ('009','single gift',DATEADD(MM,-80,GETDATE())) 
INSERT INTO #data values ('010','single gift',DATEADD(MM,-54,GETDATE())) 

et le transformer en ceci:

ID | 2005 | 2006 | 2007   | 2008 | 2009  | 2010 
001 | NULL | NULL | regular gift | NULL | Both gifts | NULL 

si, fondamentalement, si ID est à la fois un seul et un cadeau régulier pendant un an, puis l'appeler « les deux dons », s'il n'y a qu'un seul cadeau alors « cadeau unique » et s'il n'y a qu'un cadeau régulier, alors «cadeau régulier».

Ces données seraient ensuite utilisées dans le cadre d'une autre requête plus importante. Je trouve qu'il est assez facile de travailler si une carte d'identité a donné un cadeau unique ou régulier (ou les deux), mais j'ai du mal à le faire d'année en année sans créer une série des tables temporaires qui ralentit les choses massivement

Merci d'avance :)

EDIT Ceci est une version très simplifiée des données réelles que j'ai - les données réelles ont jusqu'à 200 lignes par ID, et peut contenir plusieurs dons par année de chaque type.

Répondre

2

Est-ce que ce match ce que vous avez besoin?

;with IDYearSummary as 
(
    select 
     id, 
     MAX(CASE payment_type WHEN 'single gift' THEN 1 ELSE 0 END) as single, 
     MAX(CASE payment_type WHEN 'regular gift' THEN 1 ELSE 0 END) as regular, 
     DATEPART(year,payment_date) as year 
    from 
     #data 
    group by 
     id,DATEPART(year,payment_date) 
), MixGifts as 
(
    select 
     id, 
     CASE 
      WHEN single=1 and regular=1 THEN 'both' 
      WHEN single=1 THEN 'single' 
      WHEN regular=1 THEN 'regular' 
     END as gifts, 
     year 
    from 
     IDYearSummary 
) 
select 
    id, 
    [2002], 
    [2003], 
    [2004], 
    [2005], 
    [2006], 
    [2007], 
    [2008], 
    [2009], 
    [2010] 
from 
    MixGifts 
     pivot (MAX(gifts) FOR year in ([2002],[2003],[2004],[2005],[2006],[2007],[2008],[2009],[2010])) as pvt 


drop table #data 
+0

Fantastique - fonctionne le plus rapidement pour ma table réelle ainsi acceptée comme réponse :) – Dibstar

1

Cette requête fonctionne à l'aide des données de test fournies.

Select * 
From 
(
Select ID, 
     'both gift' as 'PaymentType', 
     Datepart(Year, payment_date) as 'Years' 
From #data 
Group by Id, Datepart(Year, payment_date) 
Having Count(Distinct(Payment_Type)) > 1 

    Union All 

Select ID, 
     Max(Payment_Type), 
     Datepart(Year, payment_date) 
From #data 
Group by Id, Datepart(Year, payment_date) 
Having Count(Distinct(Payment_Type)) = 1 

    Union All 

Select ID, 
     Null, 
     Datepart(Year, payment_date) 
From #data 
Group by Id, Datepart(Year, payment_date) 
Having Count(Distinct(Payment_Type)) = 0 
)q 

Pivot (max(PaymentType) for Years in ([2002],[2003],[2004],[2005],[2006],[2007],[2008],[2009],[2010]) 
)p 
+0

Malheureusement (comme je l'ai maintenant inclus dans la question), je peux avoir plusieurs lignes par ID (jusqu'à environ 200) et il peut théoriquement être un nombre infini de lignes de chaque type de cadeau - grâce – Dibstar

+0

Est-ce que ce type de cadeau ne sera que «cadeau unique» ou «cadeau régulier» – codingbadger

+0

Oui, le type de cadeau est toujours fixe pour être soit simple soit régulier, c'est juste que pour chaque ID il peut y avoir plusieurs références de chaque pour chaque année – Dibstar

1
WITH Data AS 
    (SELECT id, YEAR(payment_date) AS payment_year, 
     CASE 
      WHEN MAX(payent_type)<> MIN(payent_type) 
      THEN 'Both gifts' 
      ELSE MAX(payent_type) 
     END AS payent_type 
    FROM #data 
    GROUP BY YEAR(payment_date), 
     id 
    ) 
select id,[2002],[2003],[2004],[2005],[2006],[2007],[2008],[2009],[2010] 
from data 
Pivot (max(payent_type) for 
     payment_year in ([2002],[2003],[2004],[2005],[2006],[2007],[2008],[2009],[2010])) pvt 
+0

Merci pour cela - comment le MAX (payment_type) <> MIN (payment_type) lorsque payment_type n'est pas un numérique? Je n'avais aucune idée que vous pouviez faire un MAX d'un VARCHAR !! :) – Dibstar

+0

Max et Min sur les chaînes signifie l'ordre alphabétique en premier et en dernier. –

+0

+1 pour prendre le temps d'expliquer la solution - fonctionne parfaitement un peu plus lentement sur ma table que la réponse acceptée. – Dibstar

Questions connexes