Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/silverlight/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如果与内部查询一起使用,SQL server pivot count函数将无法正常工作_Sql_Sql Server_Pivot_Pivot Table - Fatal编程技术网

如果与内部查询一起使用,SQL server pivot count函数将无法正常工作

如果与内部查询一起使用,SQL server pivot count函数将无法正常工作,sql,sql-server,pivot,pivot-table,Sql,Sql Server,Pivot,Pivot Table,我认为我的SQL server pivot函数中有一个bug,因为我找不到任何其他解释 我正在运行一个简单的pivot,并使用MSDN中显示的确切语法。 但是pivot答案显示了所有列的完全相同的数字,其值等于所有周的计数!!! (左边是查询结果,右边是我想要的) 我的问题是: SELECT * FROM (SELECT r.cutomer_id ,c.[Week] ,r.id FROM r JOIN c ON r.Create_date = c.Dat

我认为我的SQL server pivot函数中有一个bug,因为我找不到任何其他解释

我正在运行一个简单的pivot,并使用MSDN中显示的确切语法。 但是pivot答案显示了所有列的完全相同的数字,其值等于所有周的计数!!! (左边是查询结果,右边是我想要的)

我的问题是:

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号,周数与您从查询中得到的相同)

因此,我认为我的查询有问题,但后来我将查询更改为:

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

而且效果很好! 另外,如果我从select中删除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而不是零。

“它工作正常!!!”我非常怀疑它工作正常,因为SQL表/结果集按SQL定义是无序的,所以使用
TOP
ORDER by
是毫无意义的。。事实上,它可能导致返回非确定性(随机)结果。。要始终获得确定性(固定)结果,您应该至少包含一个列,该列具有主键、唯一键,或者您知道该列具有(几乎)唯一的值,如datetime,按顺序为7分秒,假设当您开始大量删除或更新内容,并且表/索引碎片化成为一件事情时,它将不再正常工作。。我警告过你,如果你想继续用你的查询结果玩俄罗斯轮盘赌,那么这是你的选择。对于任何在这里帮助你的人,你需要提供一个再现问题或实际执行计划(XML)的MVCE。当然,如果将完全相同的行插入临时表而不是派生表,PIVOT不应返回不同的结果。可能是数据库中的某种损坏,一个bug,或者你的描述库中缺少什么,Martin。我们有非常敏感的数据和安全的服务器,很难创建MVCE。这些是我使用的完全相同的查询,我得到了完全不同的结果!如果没有任何解释,我想我的数据库可能有问题!我会检查/重建索引,或者尝试使用查询来缩小问题范围。
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;