2016-10-20 8 views
2

Ich bin ziemlich vage vertraut mit SQL. Ich benutze SQL Server 2012.So gruppieren Sie nur nach Monat und Jahr

Ich habe diese Tabelle:

|Id | SiteId| SiteDesc |IsNormal|  DateReview   |FrequencyId| 
|3379|  5|  colon | 1 | 2016-09-10 00:00:00.000| 1  |  
|3381|  5|  colon | 0 | 2016-09-15 00:00:00.000| 1  |  
|3382|  5|  colon | 1 | 2016-09-21 00:00:00.000| 1  | 

|3489|  5|  colon | 0 | 2016-08-10 00:00:00.000| 1  |  
|3851|  5|  colon | 1 | 2016-08-16 00:00:00.000| 1  | 

|3537|  2|  dogon | 1 | 2016-05-05 00:00:00.000| 1  |  
|3863|  2|  dogon | 1 | 2016-05-20 00:00:00.000| 1  |  

IsNormal Spalte ist von BIT Datentyp.

Ich muss die Tabelle von SiteId und DateReview gruppieren (nur Monat und Jahr). Wenn in IsNormal Spalte mindestens eine Zeile die Eigenschaft false hat, muss sie in einer gruppierten Tabelle False sein.

Hier ist die gewünschte gruppiert Tabelle:

| SiteId| SiteDesc |IsNormal|  DateReview   |FrequencyId| 
|  5|  colon | 0 | 2016-09-10 00:00:00.000| 1  |   
|  5|  colon | 0 | 2016-08-10 00:00:00.000| 1  |  
|  2|  dogon | 1 | 2016-05-05 00:00:00.000| 1  |  

Danke im Voraus.

+1

@gaurav jedes Element in der Auswahl mit einer Gruppe von muss entweder in der Gruppe sein durch oder ein Aggregat: das entspricht dieser Regel nicht. – Richard

Antwort

3

SQL Server kann nicht aggregierte bit Spalten wie es ist, gegossen, so dass es zu int zuerst, dann MIN verwenden und es dann zu bit zurückgeworfen.

Zur Gruppe von Monat verwende ich die folgende Formel:

DATEADD(month, DATEDIFF(month, '20010101', DateReview), '20010101') 

Sie können jeden Anker Datum wählen anstelle von ‚20010101‘, kann es jeder erste Tag des Monats sein. Die Idee ist einfach. DATEDIFF(month,...) berechnet die Anzahl der Monate zwischen dem Ankerdatum und dem Wert aus der Tabelle. Dies ist eine ganze Zahl - wie oft die Grenze des Monats überschritten wurde. Dann wird diese Nummer zum Ankerdatum hinzugefügt. Das Ergebnis dieses Ausdrucks ist der Wert DateReview, der auf den ersten Tag des Monats gekürzt wurde.

Abfrage

SELECT 
    SiteId 
    ,MIN(SiteDesc) AS SiteDesc 
    ,CAST(MIN(CAST(IsNormal AS int)) AS bit) AS IsNormal 
    ,MIN(DateReview) AS DateReview 
    ,MIN(FrequencyId) AS FrequencyId 
FROM T 
GROUP BY 
    SiteId 
    ,DATEADD(month, DATEDIFF(month, '20010101', DateReview), '20010101') 
+1

Nur neugierig, warum nicht 'GROUP BY YEAR (DateReview), MONTH (DateReview)'? – Eric

+1

@Eric, In diesem Fall gibt es keinen Unterschied. Die Formel mit DATEDIFF ist generischer. Sie können 'week' /' viertel'/'hour'/etc anstelle von' month' verwenden, um nach einem anderen Intervall zu gruppieren. –

3

Verwenden year() und month():

select SiteId, min(SiteDesc) as SiteDesc, 
     min(case when IsNormal = 0 then 0 else 1 end) as IsNormal, 
     min(DateReview) as DateReview, 
     min(FrequencyId) as FrequencyId 
from t 
group by SiteId, year(DateReview), month(DateReview) 
order by min(DateReview) desc; 

Dieses einfach das Jahr und Monat für die Aggregation verwendet. Anschließend werden die Spaltenwerte mithilfe einer Aggregationsfunktion abgerufen. Für DateReview erscheint die entsprechende Funktion als min().

Verwandte Themen