如果与内部查询一起使用,SQL Server枢轴计数功能将无法正常工

问题描述 投票:0回答:1

我认为我的SQL服务器数据透视功能有一个错误,因为我找不到任何其他解释。

我正在运行一个简单的数据透视表并使用MSDN中显示的确切语法。但是数据答案显示所有列的完全相同的数字,其值等于所有周数! (左边是查询结果,右边是我想要的)left is query result and right is what I want[

这是我的查询:

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

它工作正常!

有人能给我一个解释吗?

sql sql-server pivot pivot-table
1个回答
1
投票

我不知道你为什么要在你的图像上显示结果。可能缺少一些信息。这是一个带有代码注释的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而不是零。

© www.soinside.com 2019 - 2024. All rights reserved.