我认为我的SQL服务器数据透视功能有一个错误,因为我找不到任何其他解释。
我正在运行一个简单的数据透视表并使用MSDN中显示的确切语法。但是数据答案显示所有列的完全相同的数字,其值等于所有周数! (左边是查询结果,右边是我想要的)
这是我的查询:
SELECT
*
FROM (SELECT
r.cutomer_id
,c.[Week]
,r.id
FROM r
JOIN c
ON r.Create_date = c.Date
WHERE Is_ride = 1
AND ((Create_date_int BETWEEN 20190302 AND 20190319)
OR (Create_date_int BETWEEN 20190406 AND 20190426))) p
PIVOT
(
COUNT(id)
FOR [Week] IN
([9], [10], [11], [12], [14], [15], [16], [17])
) AS pvt
这里有一些表示“p”输出的测试数据(我刚刚更改了id号码,周数与你从查询中获得的数字相同)
DROP TABLE IF EXISTS #t
CREATE TABLE #t (
customer_id INT
,WEEK INT
,id INT
)
INSERT #t (customer_id, WEEK, id)
VALUES (12032, 10, 8607)
, (43551, 10, 8721051)
, (55025, 10, 81200)
, (198874, 10, 861362)
, (99675, 10, 867081)
, (19387, 10, 863656)
, (12526, 10, 8603706)
, (19503, 10, 860924)
, (37597, 10, 860909)
, (136019, 10, 8610674);
所以我认为我的查询有问题但后来我将查询更改为:
SELECT
r.cutomer_id
,c.[Week]
,r.id INTO #t
FROM r
JOIN c
ON r.Create_date = c.Date
WHERE Is_ride = 1
AND ((Create_date_int BETWEEN 20190302 AND 20190319)
OR (Create_date_int BETWEEN 20190406 AND 20190426))
SELECT
*
FROM #t
PIVOT
(
COUNT(id)
FOR [Week] IN
([9], [10], [11], [12], [14], [15], [16], [17])
) AS pvt
它工作得很好!如果我从选择中删除r.id列并将其更改为count(week)
它工作正常!
如果我只改变我的where
WHERE Is_ride = 1
AND ((Create_date_int BETWEEN 20190302 AND 20190319)
OR (Create_date_int BETWEEN 20190406 AND 20190426))
and passenger_id in (43551,12032,136019)
) p
它工作正常!
有人能给我一个解释吗?
我不知道你为什么要在你的图像上显示结果。可能缺少一些信息。这是一个带有代码注释的MVCE,用于创建更大的测试数据集。
CREATE TABLE r(
id int identity,
customer_id int,
create_date date,
Create_date_int AS CONVERT( int, CONVERT( char(8), create_date, 112)),
is_ride bit)
INSERT INTO r(customer_id, create_date, is_ride)
SELECT customer_id, '20190307', 1
FROM (VALUES(1),(2),(3),(4),(5),(6),(7),(8),(9),(10))x(customer_id)
--SELECT TOP 100000
-- ABS(CHECKSUM(NEWID())) % 10,
-- DATEADD( dd, ABS(CHECKSUM(NEWID())) % 120, '2019'),
-- 1
--FROM sys.all_columns a, sys.all_columns b;
CREATE TABLE c(
[Date] date,
[Week] AS DATEPART( wk, [Date])
)
INSERT INTO c([Date])
SELECT DATEADD( dd, ROW_NUMBER() OVER( ORDER BY (SELECT NULL))-1, '2019')
FROM sys.all_columns;
从这里开始,我可以运行原始查询,提供预期结果,第10周只有1。
我还可以使用交叉选项卡运行替代查询,这是我首选的数据透视方法。
SELECT
r.customer_id
,COUNT( CASE WHEN c.[Week] = 9 THEN r.id END) AS wk9
,COUNT( CASE WHEN c.[Week] = 10 THEN r.id END) AS wk10
,COUNT( CASE WHEN c.[Week] = 11 THEN r.id END) AS wk11
,COUNT( CASE WHEN c.[Week] = 12 THEN r.id END) AS wk12
,COUNT( CASE WHEN c.[Week] = 14 THEN r.id END) AS wk14
,COUNT( CASE WHEN c.[Week] = 15 THEN r.id END) AS wk15
,COUNT( CASE WHEN c.[Week] = 16 THEN r.id END) AS wk16
,COUNT( CASE WHEN c.[Week] = 17 THEN r.id END) AS wk17
FROM r
JOIN c ON r.Create_date = c.Date
WHERE Is_ride = 1
AND (Create_date_int BETWEEN 20190302 AND 20190319
OR Create_date_int BETWEEN 20190406 AND 20190426)
GROUP BY r.customer_id
ORDER BY r.customer_id;
这也提供了正确的信息。
这两种方法都可能受益于预聚集以改善其性能。
WITH ctePreAggregate AS(
SELECT
r.customer_id
,c.[Week]
,COUNT(*) AS weeklycount
FROM r
JOIN c
ON r.Create_date = c.Date
WHERE Is_ride = 1
AND (Create_date_int BETWEEN 20190302 AND 20190319
OR Create_date_int BETWEEN 20190406 AND 20190426)
GROUP BY r.customer_id
,c.[Week]
)
SELECT
*
FROM ctePreAggregate
PIVOT
(
SUM(weeklycount)
FOR [Week] IN
([9], [10], [11], [12], [14], [15], [16], [17])
) AS pvt
ORDER BY customer_id;
WITH ctePreAggregate AS(
SELECT
r.customer_id
,c.[Week]
,COUNT(*) AS weeklycount
FROM r
JOIN c
ON r.Create_date = c.Date
WHERE Is_ride = 1
AND (Create_date_int BETWEEN 20190302 AND 20190319
OR Create_date_int BETWEEN 20190406 AND 20190426)
GROUP BY r.customer_id
,c.[Week]
)
SELECT
customer_id
,SUM( CASE WHEN [Week] = 9 THEN weeklycount ELSE 0 END) AS wk9
,SUM( CASE WHEN [Week] = 10 THEN weeklycount ELSE 0 END) AS wk10
,SUM( CASE WHEN [Week] = 11 THEN weeklycount ELSE 0 END) AS wk11
,SUM( CASE WHEN [Week] = 12 THEN weeklycount ELSE 0 END) AS wk12
,SUM( CASE WHEN [Week] = 14 THEN weeklycount ELSE 0 END) AS wk14
,SUM( CASE WHEN [Week] = 15 THEN weeklycount ELSE 0 END) AS wk15
,SUM( CASE WHEN [Week] = 16 THEN weeklycount ELSE 0 END) AS wk16
,SUM( CASE WHEN [Week] = 17 THEN weeklycount ELSE 0 END) AS wk17
FROM ctePreAggregate
GROUP BY customer_id
ORDER BY customer_id;
唯一的问题是您需要在列列表中添加一系列ISNULL()以显示PIVOT查询的NULL而不是零。