SQL Server组按月份
我有一个有这个模式的表
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
我试图得到一个查询工作,显示每个月的总计。 到目前为止,我已经尝试了DateDiff和嵌套select,但都不给我我想要的。 我认为这是最接近的:
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
但是当我应该得到价值的时候,我只会得到空值。 我错过了什么吗?
SELECT CONVERT(NVARCHAR(10), PaymentDate, 120) [Month], SUM(Amount) [TotalAmount] FROM Payments GROUP BY CONVERT(NVARCHAR(10), PaymentDate, 120) ORDER BY [Month]
你也可以尝试:
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
将NVARCHAR的维度限制为7,提供给CONVERT以仅显示“YYYY-MM”
SELECT CONVERT(NVARCHAR(7),PaymentDate,120) [Month], SUM(Amount) [TotalAmount] FROM Payments GROUP BY CONVERT(NVARCHAR(7),PaymentDate,120) ORDER BY [Month]
我更喜欢结合DATEADD
和DATEDIFF
function:
GROUP BY DATEADD(MONTH, DATEDIFF(MONTH, 0, Created),0)
这两个函数一起使date分量小于指定的date分量(即本例中的MONTH
)。
你可以将datepart位更改为YEAR
, WEEK
, DAY
等等,这是非常方便的。
你原来的SQL查询会看起来像这样(我无法testing,因为我没有你的数据集,但它应该把你放在正确的轨道上)。
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
还有一件事:如果您需要进一步处理该数据或将其映射到.NET对象,则“ Month
列将被键入为DateTime
,这也是一个很好的优势。
DECLARE @start [datetime] = 2010/4/1;
应该…
DECLARE @start [datetime] = '2010-04-01';
你所拥有的是2010年除以4,然后除以1,然后转换成date。 这是从1900-01-01第57.5天。
初始化后尝试SELECT @start
来检查这是否正确。
如果你需要经常这样做,我可能会添加一个计算列PaymentMonth
到表中:
ALTER TABLE dbo.Payments ADD PaymentMonth AS MONTH(PaymentDate) PERSISTED
它被保存并存储在表中 – 所以没有任何性能开销来查询它。 这是一个4字节的INT值 – 所以空间开销也很小。
一旦你有了这些,你可以简化你的查询是沿线的东西:
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
另一种不涉及到结果列的方法是简单地将date的date部分归零,因此2016-07-13
和2016-07-16
都是2016-07-01
– 这样做他们按月平均。
如果你有一个date
(不是datetime
)的值,那么你可以直接将它清零:
SELECT DATEADD( day, 1 - DATEPART( day, [Date] ), [Date] ), COUNT(*) FROM [Table] GROUP BY DATEADD( day, 1 - DATEPART( day, [Date] ), [Date] )
如果您有datetime
值,则需要使用CONVERT
删除时间部分:
SELECT DATEADD( day, 1 - DATEPART( day, [Date] ), CONVERT( date, [Date] ) ), COUNT(*) FROM [Table] GROUP BY DATEADD( day, 1 - DATEPART( day, [Date] ), CONVERT( date, [Date] ) )
现在,您的查询仅显式查看年= 2010年的付款,但是,我认为您的1月/ 2月/ 3月实际上代表了2009年。如果是,则需要针对该情况进行调整。 不要重新查询每列的总和值,只需要以月份为单位的date差异条件。 把其余的放在WHERE子句中。
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