0

我正在使用SQL Server 2014并且我有以下T-SQL查询来旋转我的数据:

SELECT *

FROM    

(
SELECT  

[PropertyCode],    
FORMAT([MTH], 'MMM') AS 'MthTxt',
[FY],    
ISNULL((SUM([Revenue])/SUM([GN])),0) AS 'RevByGN',    
[Market]   

FROM View1

WHERE [MTH] BETWEEN '2018-07-01' AND '2020-06-01'

AND [PropertyCode] = 'ABC'

GROUP BY [PropertyCode], [MTH], [FY], [Market]

) AS SourceTable

PIVOT
(
   AVG([RevByGN])
 FOR [MthTxt] IN ([Jul], [Aug], [Sep], [Oct], [Nov], [Dec], [Jan], [Feb], [Mar], [Apr], [May], [Jun])
) AS PivotTable

输出的摘录如下所示:输出

我的问题是突出的市场,即中国和俄罗斯。由于没有 19-20 财年的数据,因此数据透视结果不包括这 2 个市场的 19-20 财年行。

如何强制我的 Pivot 结果包含这些行?我还希望将NULL值显示为0.

根据Shnugo的解决方案添加我到目前为止所做的事情:

CREATE TABLE #temp_table (
    PropertyCode nvarchar(15),
    FY nvarchar(10),
    Market nvarchar(255)
);

INSERT INTO #temp_table VALUES
('CDM', 'FY 18-19', 'France'),
('CDM', 'FY 18-19', 'United Kingdom'),
('CDM', 'FY 18-19', 'Germany'),
('CDM', 'FY 18-19', 'Reunion'),
('CDM', 'FY 18-19', 'South Africa'),
('CDM', 'FY 18-19', 'Russia'),
('CDM', 'FY 18-19', 'Middle East'),
('CDM', 'FY 19-20', 'France'),
('CDM', 'FY 19-20', 'United Kingdom'),
('CDM', 'FY 19-20', 'Germany'),
('CDM', 'FY 19-20', 'Reunion'),
('CDM', 'FY 19-20', 'South Africa'),
('CDM', 'FY 19-20', 'Russia'),
('CDM', 'FY 19-20', 'Middle East')

;WITH temp1 AS

(
SELECT *
FROM (SELECT [PropertyCode] FROM #temp_table
      GROUP BY [PropertyCode]) t1
      CROSS JOIN (SELECT [FY] FROM #temp_table
                   GROUP BY [FY]) t2
      CROSS JOIN (SELECT [Market] FROM #temp_table
                   GROUP BY [Market]) t3
)

SELECT PivotTable.*

FROM

(
SELECT 
a.[PropertyCode],
a.[FY],
a.[Market],
ISNULL((SUM(b.[Package Revenue Excl VAT])/SUM(b.[GN])),0) AS 'GADR',
FORMAT(b.[MTH], 'MMM') AS 'MthTxt'

FROM [temp1] a
LEFT JOIN [QueryType2_v06feb2019_TBL] b ON (b.PropertyCode = a.PropertyCode AND b.FY = a.FY AND b.Market = a.Market)

WHERE b.[MTH] BETWEEN '2018-07-01' AND '2020-06-01'

GROUP BY a.[PropertyCode], b.[MTH], a.[FY], a.[Market]

)AS SourceTable

PIVOT
(
   AVG([GADR])
 FOR [MthTxt] IN ([Jul], [Aug], [Sep], [Oct], [Nov], [Dec], [Jan], [Feb], [Mar], [Apr], [May], [Jun])
) AS PivotTable

仍然无法正常工作并给我以下结果:

输出 2

4

1 回答 1

0

对于您的下一个问题,我会要求您创建一个 MCVE 来重现您的问题。最少是一些样本数据,最好以 DDL 和 DML 的形式提供。

这次我为你做了这件事。这不是您的确切问题,但它将有助于演示该方法。

首先,我们需要一个带有一些数据的模型表:

DECLARE @tbl TABLE(ID INT IDENTITY, GroupID INT, SubId CHAR(1),Sub2Id CHAR(1), SomeValue VARCHAR(100));
INSERT INTO @tbl VALUES
 (1,'a','x','a with x is First in 1')
,(1,'b','y','b with y is Second in 1')
,(1,'c','z','c with z is Third in 1')
,(2,'b','x','b with x is First in 2')
,(2,'c','z','c with z is Second in 2')
,(3,'a','y','a with y is First in 3');

--这个查询有你正在谈论的问题:

SELECT p.* 
FROM
(
    SELECT tbl.SubId
          ,tbl.GroupID
          ,tbl.Sub2Id
          ,tbl.SomeValue
    FROM @tbl tbl
) t
PIVOT
(
    MAX(SomeValue) FOR SubId IN(a,b,c)
) p
ORDER BY GroupId,Sub2Id;

结果

+---------+--------+------------------------+-------------------------+-------------------------+
| GroupID | Sub2Id | a                      | b                       | c                       |
+---------+--------+------------------------+-------------------------+-------------------------+
| 1       | x      | a with x is First in 1 | NULL                    | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 1       | y      | NULL                   | b with y is Second in 1 | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 1       | z      | NULL                   | NULL                    | c with z is Third in 1  |
+---------+--------+------------------------+-------------------------+-------------------------+
| 2       | x      | NULL                   | b with x is First in 2  | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 2       | z      | NULL                   | NULL                    | c with z is Second in 2 |
+---------+--------+------------------------+-------------------------+-------------------------+
| 3       | y      | a with y is First in 3 | NULL                    | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+

您可以看到,每个 GroupId 被提及的频率与有数据的频率一样高。第 1 组用 3 行 x、y 和 z 表示,而第 2 组用 z 和 x 表示,第 3 组只用 y 表示。

您需要的是一个固定的集合,其中包含您在任何情况下都希望看到的所有行。如果您可以确定您想要查看的任何组合在您的集合中至少存在一次,您可以直接从数据中提取它,否则您必须维护一个提供此类修复集的表。在我假设的示例中,现有数据可以提供我需要的所有内容。

--Create a combination of all existing Groups *cross joined* with all existing subs.
WITH AllCombinations AS
(
    SELECT *
    FROM (SELECT GroupID FROM @tbl GROUP BY GroupID) t1
    CROSS JOIN (SELECT Sub2Id FROM @tbl GROUP BY Sub2Id) t2
)
SELECT p.* 
FROM
(
    SELECT tbl.SubId
          ,combos.GroupID
          ,combos.Sub2Id
          ,tbl.SomeValue
    FROM AllCombinations combos
    LEFT JOIN @tbl tbl ON combos.GroupID=tbl.GroupID AND combos.Sub2Id=tbl.Sub2Id
) t
PIVOT
(
    MAX(SomeValue) FOR SubId IN(a,b,c)
) p
ORDER BY GroupId,Sub2Id;

你看,我LEFT JOIN的组合设置与实际的表。我用combos别名而不是用tbl. 这将确保这些值在结果集中并显示在透视列表中。

结果

+---------+--------+------------------------+-------------------------+-------------------------+
| GroupID | Sub2Id | a                      | b                       | c                       |
+---------+--------+------------------------+-------------------------+-------------------------+
| 1       | x      | a with x is First in 1 | NULL                    | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 1       | y      | NULL                   | b with y is Second in 1 | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 1       | z      | NULL                   | NULL                    | c with z is Third in 1  |
+---------+--------+------------------------+-------------------------+-------------------------+
| 2       | x      | NULL                   | b with x is First in 2  | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 2       | y      | NULL                   | NULL                    | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 2       | z      | NULL                   | NULL                    | c with z is Second in 2 |
+---------+--------+------------------------+-------------------------+-------------------------+
| 3       | x      | NULL                   | NULL                    | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 3       | y      | a with y is First in 3 | NULL                    | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+
| 3       | z      | NULL                   | NULL                    | NULL                    |
+---------+--------+------------------------+-------------------------+-------------------------+

更新

我试图修复您的查询,但我无法对其进行测试。所以这是在半夜蒙着眼睛飞过茂密的森林;-)

CREATE TABLE #propCodes (PropertyCode nvarchar(15));
CREATE TABLE #FYs (FY nvarchar(10));
CREATE TABLE #Markets(Market nvarchar(255));

INSERT INTO #propCodes VALUES('CDM');
INSERT INTO #FYs VALUES('FY 18-19'),('FY 19-20');
INSERT INTO #Markets VALUES
('France'),
('United Kingdom'),
('Germany'),
('Reunion'),
('South Africa'),
('Russia'),
('Middle East'),
('France');

/* Check this to see the *cartesian product*
SELECT *
FROM #propCodes
CROSS JOIN #FYs 
CROSS JOIN #Markets;
*/

;WITH temp1 AS
(
    SELECT *
    FROM #propCodes
    CROSS JOIN #FYs 
    CROSS JOIN #Markets
)
,Aggregated AS
(
    SELECT 
        [PropertyCode],
        [FY],
        [Market],
        ISNULL((SUM([Package Revenue Excl VAT])/SUM([GN])),0) AS 'GADR',
        FORMAT([MTH], 'MMM') AS 'MthTxt'
    FROM [QueryType2_v06feb2019_TBL]
    WHERE [MTH] BETWEEN '2018-07-01' AND '2020-06-01'
    GROUP BY [PropertyCode], [MTH], a.[FY], [Market]
)
SELECT PivotTable.*
FROM
(
    SELECT *
    FROM [temp1] a
    LEFT JOIN Aggregated b ON (b.PropertyCode = a.PropertyCode AND b.FY = a.FY AND b.Market = a.Market)
)AS SourceTable
PIVOT
(
   AVG([GADR])  FOR [MthTxt] IN ([Jul], [Aug], [Sep], [Oct], [Nov], [Dec], [Jan], [Feb], [Mar], [Apr], [May], [Jun])
) AS PivotTable;

我用易于维护的表替换了您的单个临时表。检查注释掉的 SELECT 看看会发生什么......

我又引入了一个 CTE 来将您的聚合/计算与旋转的LEFT JOIN.

祝你好运。如果这不起作用,请以消耗性格式提供样本数据,减少到所需的最低限度...

于 2019-05-09T07:04:37.647 回答