Frage

Ich habe eine Tabelle mit diesem Schema

ItemID    UserID    Year    IsPaid    PaymentDate  Amount
1         1         2009    0         2009-11-01  300
2         1         2009    0         2009-12-01  342
3         1         2010    0         2010-01-01  243
4         1         2010    0         2010-02-01  2543
5         1         2010    0         2010-03-01  475

Ich versuche, eine Abfrage zum Laufen zu bringen, die die Gesamtsummen für jeden Monat anzeigt.Bisher habe ich DateDiff und verschachtelte Auswahlen ausprobiert, aber keines von beiden liefert mir das, was ich will.Das kommt meiner Meinung nach am nächsten:

DECLARE @start [datetime] = 2010/4/1;
SELECT ItemID, IsPaid,
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 And DateDiff(m, PaymentDate, @start) = 0 AND UserID = 100) AS "Apr",
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =1 AND UserID = 100) AS "May",
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =2 AND UserID = 100) AS "Jun", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =3 AND UserID = 100) AS "Jul", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =4  AND UserID = 100) AS "Aug", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =5  AND UserID = 100) AS "Sep", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =6  AND UserID = 100) AS "Oct", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =7 AND UserID = 100) AS "Nov", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =8 AND UserID = 100) AS "Dec", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =9 AND UserID = 100) AS "Jan", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =10 AND UserID = 100) AS "Feb", 
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 AND DateDiff(m, PaymentDate, @start) =11 AND UserID = 100) AS "Mar" 
FROM LIVE L INNER JOIN Payments I ON I.LiveID = L.RECORD_KEY 
WHERE UserID = 16178 

Aber ich bekomme nur Nullen, wenn ich Werte bekommen sollte.Vermisse ich etwas?

War es hilfreich?

Lösung

SELECT CONVERT(NVARCHAR(10), PaymentDate, 120) [Month], SUM(Amount) [TotalAmount]
FROM Payments
GROUP BY CONVERT(NVARCHAR(10), PaymentDate, 120)
ORDER BY [Month]

Sie können es auch versuchen:

SELECT DATEPART(Year, PaymentDate) Year, DATEPART(Month, PaymentDate) Month, SUM(Amount) [TotalAmount]
FROM Payments
GROUP BY DATEPART(Year, PaymentDate), DATEPART(Month, PaymentDate)
ORDER BY Year, Month

Andere Tipps

Beschränken Sie die Dimension des Nvarchar auf 7, um nur "yyyy-mm" zu konvertieren, um nur "yyyy-mm" zu zeigen.

SELECT CONVERT(NVARCHAR(7),PaymentDate,120) [Month], SUM(Amount) [TotalAmount]
FROM Payments
GROUP BY CONVERT(NVARCHAR(7),PaymentDate,120)
ORDER BY [Month]

Ich kombiniere lieber DATEADD Und DATEDIFF funktioniert so:

GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Created),0)

Zusammen setzen diese beiden Funktionen die Datumskomponente auf Null kleiner als die angegebene Datumsteil (d. h. MONTH in diesem Beispiel).

Sie können das ändern Datumsteil bisschen zu YEAR, WEEK, DAY, usw...Das ist super praktisch.

Ihre ursprüngliche SQL-Abfrage würde dann etwa so aussehen (ich kann sie nicht testen, da ich Ihren Datensatz nicht habe, aber sie sollte Sie auf den richtigen Weg bringen).

DECLARE @start [datetime] = '2010-04-01';

SELECT
    ItemID,
    UserID,
    DATEADD(MONTH, DATEDIFF(MONTH, 0, Created),0) [Month],
    IsPaid,
    SUM(Amount)
FROM LIVE L
INNER JOIN Payments I ON I.LiveID = L.RECORD_KEY
WHERE UserID = 16178
AND PaymentDate > @start

Eine Sache noch:Die Month Die Spalte wird als a eingegeben DateTime Dies ist auch ein schöner Vorteil, wenn Sie diese Daten weiter verarbeiten oder sie beispielsweise einem .NET-Objekt zuordnen müssen.

DECLARE @start [datetime] = 2010/4/1;

Sollte sein...

DECLARE @start [datetime] = '2010-04-01';

Die, die Sie haben, dividiert 2010 durch 4, dann um 1 und konvertiert dann auf ein Datum. Das ist der 57.5. Tag von 1900-01-01.

Versuchen SELECT @start Nach Ihrer Initialisierung, um zu überprüfen, ob dies korrekt ist.

Wenn Sie dies häufig tun müssen, würde ich wahrscheinlich eine berechnete Spalte hinzufügen PaymentMonth zum Tisch:

ALTER TABLE dbo.Payments ADD PaymentMonth AS MONTH(PaymentDate) PERSISTED

Es ist in dem Tisch bestehen und gespeichert - es gibt also wirklich keine Leistung, die es abfragt. Es ist ein 4 -Byte -Int -Wert - also ist auch der Space Overhead minimal.

Sobald Sie das haben, können Sie Ihre Abfrage so vereinfachen, dass Sie etwas in der Sicht haben:

SELECT ItemID, IsPaid,
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 And PaymentMonth = 1 AND UserID = 100) AS 'Jan',
(SELECT SUM(Amount) FROM Payments WHERE Year = 2010 And PaymentMonth = 2 AND UserID = 100) AS 'Feb',
.... and so on .....
FROM LIVE L 
INNER JOIN Payments I ON I.LiveID = L.RECORD_KEY 
WHERE UserID = 16178 

Ein anderer Ansatz, der nicht das Hinzufügen von Spalten zum Ergebnis besteht day Komponente des Datums so 2016-07-13 und 2016-07-16 wäre beides 2016-07-01 - damit sie nach Monat gleich machen.

Wenn Sie eine haben date (kein datetime) Wert, dann können Sie es direkt null:

SELECT
    DATEADD( day, 1 - DATEPART( day, [Date] ), [Date] ),
    COUNT(*)
FROM
    [Table]
GROUP BY
    DATEADD( day, 1 - DATEPART( day, [Date] ), [Date] )

Wenn Sie haben datetime Werte, Sie müssen verwenden CONVERT Um den Tagesabschnitt zu entfernen:

SELECT
    DATEADD( day, 1 - DATEPART( day, [Date] ),  CONVERT( date, [Date] ) ),
    COUNT(*)
FROM
    [Table]
GROUP BY
    DATEADD( day, 1 - DATEPART( day, [Date] ),  CONVERT( date, [Date] ) )

Jetzt prüft Ihre Abfrage ausdrücklich nur Zahlungen für das Jahr = 2010, aber ich denke, Sie wollten, dass Ihr Jan/Februar/Mar tatsächlich 2009 repräsentiert. Wenn ja, müssen Sie dies für diesen Fall ein wenig anpassen. Behalten Sie die Summenwerte für jede Spalte nicht weiter, sondern nur die Bedingung der Datumsdifferenz in Monaten. Legen Sie den Rest in die Where -Klausel.

SELECT 
      SUM( case when DateDiff(m, PaymentDate, @start) = 0 
           then Amount else 0 end ) AS "Apr",
      SUM( case when DateDiff(m, PaymentDate, @start) = 1 
           then Amount else 0 end ) AS "May",
      SUM( case when DateDiff(m, PaymentDate, @start) = 2 
           then Amount else 0 end ) AS "June",
      SUM( case when DateDiff(m, PaymentDate, @start) = 3 
           then Amount else 0 end ) AS "July",
      SUM( case when DateDiff(m, PaymentDate, @start) = 4 
           then Amount else 0 end ) AS "Aug",
      SUM( case when DateDiff(m, PaymentDate, @start) = 5 
           then Amount else 0 end ) AS "Sep",
      SUM( case when DateDiff(m, PaymentDate, @start) = 6 
           then Amount else 0 end ) AS "Oct",
      SUM( case when DateDiff(m, PaymentDate, @start) = 7 
           then Amount else 0 end ) AS "Nov",
      SUM( case when DateDiff(m, PaymentDate, @start) = 8 
           then Amount else 0 end ) AS "Dec",
      SUM( case when DateDiff(m, PaymentDate, @start) = 9 
           then Amount else 0 end ) AS "Jan",
      SUM( case when DateDiff(m, PaymentDate, @start) = 10 
           then Amount else 0 end ) AS "Feb",
      SUM( case when DateDiff(m, PaymentDate, @start) = 11 
           then Amount else 0 end ) AS "Mar"
   FROM 
      Payments I
         JOIN Live L
            on I.LiveID = L.Record_Key
   WHERE 
          Year = 2010 
      AND UserID = 100
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top