我有一个SQL Server表,该合同的日期为Start
(1-1-2017)和End
(1-1-2022),并且每月和每月都生成当前和过去几个月的发票
即使没有生成发票,我也想将月份显示为列,仅使用SQL / Pivot表或必须创建以日历为日期的表可以吗?
到目前为止,我已经使用此代码。
WITH CTE_MyTable AS
(
SELECT
FORMAT(MIN(StartDate), 'yyyy-MM') AS [MyDate]
FROM
MyTable
UNION ALL
SELECT
FORMAT(MIN(DATEADD(month, 1, StartDate)), 'yyyy-MM') AS [MyDate]
FROM
MyTable
WHERE
FORMAT(DATEADD(month, 1, StartDate),'yyyy-MM') <= (SELECT FORMAT(MAX(EndDate), 'yyyy-MM') AS [MyDate] FROM MyTable)
)
SELECT [MyDate]
FROM CTE_ MyTable
GROUP BY MyDate
OPTION (MAXRECURSION 0);
答案 0 :(得分:0)
因此,假设您的表如下所示(使用temp变量,因此您只需复制/粘贴/测试即可):
DECLARE @sale TABLE(saledate DATE, saleamt MONEY);
INSERT @sale VALUES ('20170103',500),('20170128',266),('20170303',4002),('20170409',25);
请注意,为简单起见,我只做了6个月。以下查询获取每月销售额(第一个查询)和第二个查询的销售额之和:
DECLARE @sale TABLE(saledate DATE, saleamt MONEY);
INSERT @sale VALUES ('20170103',500),('20170128',266),('20170303',4002),('20170409',25);
SELECT
[201701] = COUNT(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 1 THEN 1 END),
[201702] = COUNT(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 2 THEN 1 END),
[201703] = COUNT(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 3 THEN 1 END),
[201704] = COUNT(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 4 THEN 1 END),
[201705] = COUNT(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 5 THEN 1 END),
[201706] = COUNT(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 6 THEN 1 END)
FROM @sale t;
SELECT
[201701] = ISNULL(SUM(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 1 THEN t.saleamt END),0),
[201702] = ISNULL(SUM(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 2 THEN t.saleamt END),0),
[201703] = ISNULL(SUM(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 3 THEN t.saleamt END),0),
[201704] = ISNULL(SUM(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 4 THEN t.saleamt END),0),
[201705] = ISNULL(SUM(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 5 THEN t.saleamt END),0),
[201706] = ISNULL(SUM(CASE WHEN YEAR(t.saledate)=2017 AND MONTH(t.saledate) = 6 THEN t.saleamt END),0)
FROM @sale t;
这些查询返回:
201701 201702 201703 201704 201705 201706
----------- ----------- ----------- ----------- ----------- -----------
2 0 1 1 0 0
201701 201702 201703 201704 201705 201706
--------------------- --------------------- --------------------- --------------------- --------------------- ---------------------
766.00 0.00 4002.00 25.00 0.00 0.00
答案 1 :(得分:0)
有一种方法可以使用Pivot()
函数在SQL中旋转列(Microsoft文档位于https://docs.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot?view=sql-server-2017)
要将月份显示为列(1至12),Pivot()
函数将值分配给(硬编码)列。正确实施后,由于缺少记录,有一些NULL不会发生聚合。用COALESCE()
函数隐含用零代替NULL的方法。
应该对数据透视表的年份值进行分组,并且对于数据透视表没有特定的Group By
,这由 SourceTable 查询的编写方式暗示。
在此示例代码中,我使用与官方文档相同的确切格式;除了我另外按年份分组并且将COALESCE
NULL与0组合在一起。
我正在做的是计算给定月份和年份的记录数:
SELECT yearval
,COALESCE([1], 0) [Jan]
,COALESCE([2], 0) [Feb]
,COALESCE([3], 0) [Mar]
,COALESCE([4], 0) [Apr]
,COALESCE([5], 0) [May]
,COALESCE([6], 0) [Jun]
,COALESCE([7], 0) [Jul]
,COALESCE([8], 0) [Aug]
,COALESCE([9], 0) [Sep]
,COALESCE([10], 0) [Oct]
,COALESCE([11], 0) [Nov]
,COALESCE([12], 0) [Dec]
FROM
(SELECT YEAR([Your_Date_Column_Here]) AS [yearval]
,MONTH([Your_Date_Column_Here]) AS [monthval]
FROM [Your_Table_Name_Here]) AS SourceTable
PIVOT
(
COUNT(monthval) FOR monthval IN ([1], [2], [3], [4], [5], [6], [7], [8], [9], [10], [11], [12])
) AS PivotTable
将在我的测试数据库中产生以下输出:
yearval Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
2015 1952 1122 1678 2364 1125 1308 1414 2103 1031 1340 2506 1015
2016 1123 1413 1568 1421 1278 1252 1048 1290 1251 1571 2647 1253
2017 0 0 0 3 0 1241 2377 2714 6724 1388 1521 1243
2018 2127 2118 2449 2330 2687 3833 3279 883 0 0 0 0