Как изменить мой сводный запрос, чтобы строки с нулевыми значениями не исключались в выходных данных? - PullRequest
0 голосов
/ 09 мая 2019

Я использую 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

Выдержка из вывода показана ниже: output

Моя проблема связана с выделенными рынками, а именно с Китаем и Россией. Поскольку данных за 19-20 ФГ нет, в сводные результаты не включены строки 19-20 ФГ для этих 2 рынков.

Как я могу заставить мои результаты Pivot включать эти строки? Я также хотел бы, чтобы значения NULL отображались как 0.

Добавление того, что я уже сделал, на основе решения Шнуго:

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

Все еще не работает и дает мне следующие результаты:

output 2

1 Ответ

0 голосов
/ 09 мая 2019

Для вашего следующего вопроса я бы попросил вас создать 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;

Вы видите, что I 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.

Удачи.Если это не помогает, предоставьте образцы данных в формате расходных материалов, сведенные до необходимого минимума ...

...