Как экспортировать отчет и пометить столбец с данными? - PullRequest
1 голос
/ 11 октября 2019

Это сложно объяснить, но я попробую. Мне нужно экспортировать отчет, который показывает, какие магазины имеют местоположения и в каких штатах.

Предположим, у меня есть следующая таблица:

+----------+-----------+
| STORE_ID | STATE_ABV |
+----------+-----------+
|        1 | AK        |
|        1 | AL        |
|        1 | AR        |
|        2 | MI        |
|        2 | OH        |
|        2 | IN        |
|        3 | CA        |
|        3 | NV        |
+----------+-----------+

Столбец STORE_ID является ключом к другой таблице, гдеМне просто нужно вытащить столбец STORE_NAME.

+----------+------------+
| STORE_ID | STORE_NAME |
+----------+------------+
|        1 | Walmart    |
|        2 | Target     |
|        3 | Kroeger's  |
+----------+------------+

Я хочу экспортировать список каждого магазина вместе со столбцами для всех состояний. Если хранилище доступно в этом состоянии, я хочу поместить «X» для значения.

Таким образом, желаемый вывод выглядит следующим образом:

+------------+----+----+----+----+----+----+----+----+
| STORE_NAME | AK | AL | AR | CA | IN | OH | MI | NV |
+------------+----+----+----+----+----+----+----+----+
| Walmart    | X  | X  | X  |    |    |    |    |    |
| Target     |    |    |    |    | X  | X  | X  |    |
| Kroeger's  |    |    |    | X  |    |    |    | X  |
+------------+----+----+----+----+----+----+----+----+

Возможно ли это в SQL Server? Как бы я написал такой запрос? Должен быть столбец для каждого STATE_ABV, который существует в таблице.

Ответы [ 2 ]

2 голосов
/ 11 октября 2019

Как уже упоминалось, вы здесь, чтобы повернуть ваши данные. Лично мне не нравится функциональность PIVOT SQL Server, и гораздо больше я предпочитаю использовать кросс-таб (условное агрегирование).

Поскольку я подозреваю, что для этого потребуется динамический разворот, я также сделал это:

--Sample tables
CREATE TABLE dbo.StoreLocations (StoreID int,
                                 StateAbv char(2));
CREATE TABLE dbo.Stores (StoreID int IDENTITY,
                         StoreName varchar(20));
GO
--Sample data
INSERT INTO dbo.Stores (StoreName)
VALUES('Walmart'),('Target'),('Kroeger''s');

INSERT INTO dbo.StoreLocations (StoreID,StateAbv)
VALUES(1,'AK'),
      (1,'AL'),
      (1,'AR'),
      (2,'MI'),
      (2,'OH'),
      (2,'IN'),
      (3,'CA'),
      (3,'NV');
GO
--Quick sample to get the format right
SELECT S.StoreName,
       IIF(COUNT(CASE WHEN SL.StateAbv = 'AK' THEN 1 END) = 0,NULL, 'X') AS AK
FROM dbo.Stores S
     LEFT JOIN dbo.StoreLocations SL ON S.StoreID = SL.StoreID
GROUP BY S.StoreName;
GO
--The real solution
DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT S.StoreName,' + NCHAR(13) + NCHAR(10) +
           STUFF((SELECT N',' + NCHAR(13) + NCHAR(10) +
                         N'       IIF(COUNT(CASE WHEN SL.StateAbv = ' + QUOTENAME(SL.StateAbv,'''') + N' THEN 1 END) = 0, NULL,''X'') AS ' + QUOTENAME(SL.StateAbv)
                  FROM dbo.StoreLocations SL
                  GROUP BY SL.StateAbv --Could use DISTINCT too
                  ORDER BY SL.StateAbv
                  FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,3,N'') + NCHAR(13) + NCHAR(10) +
           N'FROM dbo.Stores S' + NCHAR(13) + NCHAR(10) +
           N'     LEFT JOIN dbo.StoreLocations SL ON S.StoreID = SL.StoreID' + NCHAR(13) + NCHAR(10) +
           N'GROUP BY S.StoreName;';

PRINT @SQL; --Your best friend

EXEC sp_executesql @SQL;

GO

--Clean up
DROP TABLE dbo.Stores;
DROP TABLE dbo.StoreLocations;

db <> fiddle

Я по глупости предположил, что состояние было уникальным в StoreLocations. В идеале у вас также должна быть таблица States, тогда вам не нужно получать отдельные состояния из таблицы StoreLocations.

Пример с таблицей States: db <> скрипка

1 голос
/ 11 октября 2019

На всякий случай, если вам нужен динамический разворот. Лично я не против PIVOT. Это просто еще одна отвертка в наборе инструментов.

Часть UNION ALL можно удалить, если вы не обращаете внимания на значения NULL

Пример dbFiddle

Declare @SQL varchar(max) = '
Select *
From (
      Select A.Store_ID
            ,A.State_Abv
            ,B.Store_Name
            ,Value = ''X''
       From  StoreLocations A
       Join  Stores         B on  A.Store_ID=B.Store_ID
       Union All
       Select B.Store_ID
             ,A.State_Abv
             ,B.Store_Name
            ,Value = ''''
      From  (Select Distinct State_Abv from StoreLocations) A
      Cross Join Stores    B 
     ) A
 Pivot (max(Value) For [State_Abv] in (' + Stuff((Select Distinct ',' + QuoteName(State_Abv) From  StoreLocations Order By 1 For XML Path('')),1,1,'')  + ') ) p
 Order By Store_ID
'

Exec(@SQL)

Возвращает

enter image description here

Опция со значениями NULL

Declare @SQL varchar(max) = '
Select *
From (
      Select A.Store_ID
            ,A.State_Abv
            ,B.Store_Name
            ,Value = ''X''
       From  StoreLocations A
       Join  Stores         B on  A.Store_ID=B.Store_ID
     ) A
 Pivot (max(Value) For [State_Abv] in (' + Stuff((Select Distinct ',' + QuoteName(State_Abv) From  StoreLocations Order By 1 For XML Path('')),1,1,'')  + ') ) p
 Order By Store_ID
'

Возврат

enter image description here

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...