Sql server 获取SQL动态(日历)数据透视表的总计
我正在尝试使用SQL Server动态透视表,该表允许我计算列数,然后求和列数。透视表的目的是创建一个报告,其中包括个人在一个城市停留的所有天数以及总天数(一个月内)。因此,例如,人员A在6月份每天都会停留-总数将为30。人员B仅在6月3日开始停留-总数将为27等。数据表仅包含姓名、ArriveDate、DepartDate…通过SQL查询创建当月的天数Sql server 获取SQL动态(日历)数据透视表的总计,sql-server,pivot-table,dynamic-tables,Sql Server,Pivot Table,Dynamic Tables,我正在尝试使用SQL Server动态透视表,该表允许我计算列数,然后求和列数。透视表的目的是创建一个报告,其中包括个人在一个城市停留的所有天数以及总天数(一个月内)。因此,例如,人员A在6月份每天都会停留-总数将为30。人员B仅在6月3日开始停留-总数将为27等。数据表仅包含姓名、ArriveDate、DepartDate…通过SQL查询创建当月的天数 +------+------------+------------+-------+-------+-------+-----+------
+------+------------+------------+-------+-------+-------+-----+-------+-------+-------+
|姓名|到达日期|出发日期| 06-01 | 06-02 | 06-03 |……|06-29 | 06-30 |总计|
+------+------------+------------+-------+-------+-------+-----+-------+-------+-------+
|A | 2014-06-01 | 2014-06-23 | 1 | 1 | 1 |……|1 | 1 | 30 |
|B | 2014-06-02 | 2014-06-23 | 0 | 1 | 1 |……|1 | 1 | 27 |
|C | 2014-06-02 | 2014-06-23 | 0 | 0 | 0 |……|1 | 1 | 16 |
+------+------------+------------+-------+-------+-------+-----+-------+-------+-------+
以下是我使用动态交叉表的尝试:
样本数据:
Name ArriveDate DepartDate
---- ---------- ----------
A 2015-07-01 2015-07-23
B 2015-07-02 2015-07-04
C 2015-07-03 2015-07-31
动态交叉表解决方案:
DECLARE @minDate AS DATE,
@maxDate AS DATE
SELECT @minDate = DATEADD(DAY, 1, EOMONTH(GETDATE(), -1)),
@maxDate = EOMONTH(GETDATE())
CREATE TABLE #dates(dt DATE)
DECLARE @sql1 VARCHAR(MAX) = '',
@sql2 VARCHAR(MAX) = '',
@sql3 VARCHAR(MAX) = '';
WITH E1(N) AS(
SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b),
E8(N) AS(SELECT 1 FROM E4 a CROSS JOIN E4 b),
Tally(N) AS(
SELECT TOP(DATEDIFF(DAY, @minDate, @maxDate) + 1)
ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM E8
)
INSERT INTO #dates
SELECT DATEADD(DAY, N - 1, @minDate)
FROM Tally
SELECT @sql1 =
'SELECT
r.Name
, r.ArriveDate
, r.DepartDate' + CHAR(10)
SELECT @sql2 = @sql2 +
' , SUM(CASE WHEN d.dt = CAST(''' + CONVERT(VARCHAR(8), dt, 112) + ''' AS DATE) THEN 1 ELSE 0 END) AS '
+ QUOTENAME(CONVERT(VARCHAR(10), dt, 120)) + CHAR(10)
FROM #dates
ORDER BY dt
SELECT @sql2 = @sql2 +
' , COUNT(d.dt) AS [total]' + CHAR(10)
SELECT @sql3 =
'FROM Reservation r
LEFT JOIN #dates d
ON d.dt BETWEEN r.ArriveDate AND r.DepartDate
GROUP BY
r.Name, r.ArriveDate, r.DepartDate'
PRINT (@sql1 + @sql2 + @sql3)
EXEC (@sql1 + @sql2 + @sql3)
DROP TABLE #dates
结果:
Name ArriveDate DepartDate 2015-07-01 2015-07-02 2015-07-03 ..... 2015-07-29 2015-07-30 2015-07-31 total
---- ---------- ---------- ----------- ----------- ----------- ..... ----------- ----------- ----------- -----------
A 2015-07-01 2015-07-23 1 1 1 ..... 0 0 0 23
B 2015-07-02 2015-07-04 0 1 1 ..... 0 0 0 3
C 2015-07-03 2015-07-31 0 0 1 ..... 1 1 1 29
以下是我使用动态交叉表的尝试: 样本数据:
Name ArriveDate DepartDate
---- ---------- ----------
A 2015-07-01 2015-07-23
B 2015-07-02 2015-07-04
C 2015-07-03 2015-07-31
动态交叉表解决方案:
DECLARE @minDate AS DATE,
@maxDate AS DATE
SELECT @minDate = DATEADD(DAY, 1, EOMONTH(GETDATE(), -1)),
@maxDate = EOMONTH(GETDATE())
CREATE TABLE #dates(dt DATE)
DECLARE @sql1 VARCHAR(MAX) = '',
@sql2 VARCHAR(MAX) = '',
@sql3 VARCHAR(MAX) = '';
WITH E1(N) AS(
SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)
),
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b),
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b),
E8(N) AS(SELECT 1 FROM E4 a CROSS JOIN E4 b),
Tally(N) AS(
SELECT TOP(DATEDIFF(DAY, @minDate, @maxDate) + 1)
ROW_NUMBER() OVER(ORDER BY (SELECT NULL))
FROM E8
)
INSERT INTO #dates
SELECT DATEADD(DAY, N - 1, @minDate)
FROM Tally
SELECT @sql1 =
'SELECT
r.Name
, r.ArriveDate
, r.DepartDate' + CHAR(10)
SELECT @sql2 = @sql2 +
' , SUM(CASE WHEN d.dt = CAST(''' + CONVERT(VARCHAR(8), dt, 112) + ''' AS DATE) THEN 1 ELSE 0 END) AS '
+ QUOTENAME(CONVERT(VARCHAR(10), dt, 120)) + CHAR(10)
FROM #dates
ORDER BY dt
SELECT @sql2 = @sql2 +
' , COUNT(d.dt) AS [total]' + CHAR(10)
SELECT @sql3 =
'FROM Reservation r
LEFT JOIN #dates d
ON d.dt BETWEEN r.ArriveDate AND r.DepartDate
GROUP BY
r.Name, r.ArriveDate, r.DepartDate'
PRINT (@sql1 + @sql2 + @sql3)
EXEC (@sql1 + @sql2 + @sql3)
DROP TABLE #dates
结果:
Name ArriveDate DepartDate 2015-07-01 2015-07-02 2015-07-03 ..... 2015-07-29 2015-07-30 2015-07-31 total
---- ---------- ---------- ----------- ----------- ----------- ..... ----------- ----------- ----------- -----------
A 2015-07-01 2015-07-23 1 1 1 ..... 0 0 0 23
B 2015-07-02 2015-07-04 0 1 1 ..... 0 0 0 3
C 2015-07-03 2015-07-31 0 0 1 ..... 1 1 1 29
尝试将代码放入代码格式块,这很有趣!尝试将代码放入代码格式块,这很有趣!没问题,很高兴我能帮忙。没问题,很高兴我能帮忙。