Первое, что нужно понять о сводках: вы выбираете один столбец в наборе результатов, который будет действовать как якорь PIVOT
, шарнир, вокруг которого будут вращаться данные, это указано в предложении FOR
.
Вы можете только PIVOT
FOR
один столбец, но вы можете создать этот столбец в подзапросе или из объединений или представлений в качестве целевого запроса данных, OP имеетиспользуется ROW_NUMBER()
, но вы можете использовать любой механизм SQL, какой пожелаете, даже оператор CASE
, чтобы создать пользовательский столбец для поворота, если в наборе данных нет естественного столбца для использования.
PIVOT
создаст столбец для каждого значения в столбце FOR
и даст этому столбцу значение функции агрегирования, которую выуказать
Это помогает визуализировать построенный набор записей, прежде чем применять сводную диаграмму, следующий SQL может воссоздать сценарий данных, представленный OP.Я использовал здесь переменные таблиц вместо таблиц и представлений OP.
-- template13_ticker_data (with sector_char added)
DECLARE @tickerData Table
(
sector INT,
ticker CHAR(4),
m_ticker CHAR(4),
sector_char char(10)
)
-- template13_vw
DECLARE @Company Table
(
m_ticker CHAR(4),
ticker CHAR(4),
company_name VARCHAR(100)
)
INSERT INTO @tickerData (sector, ticker)
VALUES (5 ,'ADNT')
,(5 ,'AUTO')
,(5 ,'THRM')
,(5 ,'ALSN')
,(5 ,'ALV')
,(12,'HES')
,(12,'AM')
,(12,'PHX')
,(12,'NBR')
,(12,'AMRC')
INSERT INTO @Company (ticker, company_name)
VALUES ('ADNT','Adient PLC')
,('AUTO','Autobytel Inc.')
,('THRM','Gentherm Inc')
,('ALSN','Allison Transmission Holdings, Inc.')
,('ALV ','Autoliv, Inc.')
,('HES ','Hess Corporation')
,('AM ','Antero Midstrm')
,('PHX ','Panhandle Royalty Company')
,('NBR ','Nabors Industries Ltd.')
,('AMRC','Ameresco, Inc.')
-- Just re-creating a record set that matches the given data and query structure
UPDATE @tickerData SET m_ticker = ticker
UPDATE @Company SET m_ticker = ticker
-- populate 'sector_char' to show multiple aggregates
UPDATE @tickerData SET sector_char = '|' + cast(sector as varchar) + '|'
-- Unpivoted data Proof
SELECT d.sector, d.sector_char, d.ticker, v.company_name, ROW_NUMBER() OVER(PARTITION BY d.sector ORDER BY d.sector) rn
FROM @tickerData d, @Company v
WHERE d.m_ticker = v.m_ticker
Данные перед сводкой выглядят так:
sector sector_char ticker company_name rn
------------------------------------------------------------------------
5 |5| ADNT Adient PLC 1
5 |5| AUTO Autobytel Inc. 2
5 |5| THRM Gentherm Inc 3
5 |5| ALSN Allison Transmission Holdings, Inc. 4
5 |5| ALV Autoliv, Inc. 5
12 |12| HES Hess Corporation 1
12 |12| AM Antero Midstrm 2
12 |12| PHX Panhandle Royalty Company 3
12 |12| NBR Nabors Industries Ltd. 4
12 |12| AMRC Ameresco, Inc. 5
Теперь визуализируйте подмножество результатов, которые выожидаем, чтобы показать ограничения для нескольких операций со столбцами, которые я создал sector_char
для включения в окончательный вывод
sector sector_char ticker_1 company_1 ticker_2 company_2
-----------------------------------------------------------------------------
5 |5| ADNT Adient PLC AUTO Autobytel Inc.
12 |12| HES Hess Corporation AM Antero Midstrm
Поскольку мы хотим, чтобы более 1 столбца выводилось из исходного вывода строки, (ticker
и company
из каждой строки) мы должны использовать один из следующих методов:
- Объединить значения из нескольких столбцов в один столбец
- Полезно, только если вы можете легко разбитьэти столбцы, прежде чем вам нужно использовать отдельные значения, или если вам не нужно обрабатывать столбцы, это просто для визуализации.
- выполнить несколько запросов
PIVOT
и присоединиться крезультаты - Необходимы, когда логика агрегирования различна для каждого столбца или вы не просто переносите значение строки в значение столбца (агрегированиеng несколько строк в ответе одной ячейки.)
- В подобных сценариях, когда мы просто переносим значение (например, результат агрегата будет соответствовать исходному значению ячейки), я считаю это немного hack , но также может иметь меньший синтаксис, чем альтернативный.
Я говорю hack , потому что базовая логика PIVOT дублируется, что усложняет обслуживание по мере развития запроса.
- выполнить один
PIVOT
для уникального столбца, объединиться с другими таблицами, чтобы создать дополнительные столбцы - Это легко допускает неограниченное количество дополнительных строк в выводе.
PIVOT
разрешает идентификатор таблицы, которая содержит несколько значений, которые мы хотим отобразить в окончательных результатах.
Давайте сначала посмотрим на 3, так как это демонстрируетодин PIVOT и как включить несколько столбцов для каждого из результатов PIVOT:
В этом примере я допустил до 8 результатов для каждого сектора, важно отметить, что вы ДОЛЖНЫ укажите все выходные столбцы из PIVOT
, он не является динамическим.
Вы можете использовать динамические запросы для проверки максимального количества нужных вам столбцов и сгенерировать следующий запрос на основе этих результатов.
Также обратите внимание, чтов этом решении нам не нужно присоединяться к таблице template13_vw
в исходном запросе PIVOT
, вместо этого мы присоединились к результату, поэтому стержень возвращает m_ticker
(который я считаю ключевым) вместо ticker
, который отображается в конечном результате.
-- NOTE: using CTE here, you could use table variables, temporary tables or whatever else you need
;WITH TickersBySector as
(
-- You must specify the fixed number of columns in the output
SELECT sector, sector_char, [1] as [m_ticker_1],[2] as [m_ticker_2],[3] as [m_ticker_3],[4] as [m_ticker_4],[5] as [m_ticker_5],[6] as [m_ticker_6],[7] as [m_ticker_7],[8] as [m_ticker_8]
FROM (
SELECT d.sector, d.sector_char, d.m_ticker, ROW_NUMBER() OVER(PARTITION BY d.sector ORDER BY d.sector) rn
FROM template13_ticker_data d /* OPs Syntax */
-- FROM @tickerData d /* Use this with the proof table variables */
) data
PIVOT (
MAX(m_ticker)
FOR rn IN ( [1],[2],[3],[4],[5],[6],[7],[8])
) as PivotTable
)
-- To use with the proof table variables, replace 'template13_vw' with '@Company'
SELECT sector, sector_char
,c1.[ticker] as [ticker_1], c1.company_name as [company_1]
,c2.[ticker] as [ticker_2], c2.company_name as [company_2]
,c3.[ticker] as [ticker_3], c3.company_name as [company_3]
,c4.[ticker] as [ticker_4], c4.company_name as [company_4]
,c5.[ticker] as [ticker_5], c5.company_name as [company_5]
,c6.[ticker] as [ticker_6], c6.company_name as [company_6]
,c7.[ticker] as [ticker_7], c7.company_name as [company_7]
,c8.[ticker] as [ticker_8], c8.company_name as [company_8]
FROM TickersBySector
LEFT OUTER JOIN template13_vw c1 ON c1.m_ticker = TickersBySector.m_ticker_1
LEFT OUTER JOIN template13_vw c2 ON c2.m_ticker = TickersBySector.m_ticker_2
LEFT OUTER JOIN template13_vw c3 ON c3.m_ticker = TickersBySector.m_ticker_3
LEFT OUTER JOIN template13_vw c4 ON c4.m_ticker = TickersBySector.m_ticker_4
LEFT OUTER JOIN template13_vw c5 ON c5.m_ticker = TickersBySector.m_ticker_5
LEFT OUTER JOIN template13_vw c6 ON c6.m_ticker = TickersBySector.m_ticker_6
LEFT OUTER JOIN template13_vw c7 ON c7.m_ticker = TickersBySector.m_ticker_7
LEFT OUTER JOIN template13_vw c8 ON c8.m_ticker = TickersBySector.m_ticker_8
Ниже приведен один и тот же запрос, использующий несколько PIVOT
запросов, соединенных вместе.Обратите внимание, что в этом сценарии не важно, чтобы оба PIVOT
возвращали дополнительный общий столбец sector_char
, поэтому используйте этот стиль синтаксиса, когда агрегат или дополнительный общий столбец могут отличаться для разных наборов результатов.
;WITH TickersBySector as
(
-- You must specify the fixed number of columns in the output
SELECT sector, sector_char, [1] as [ticker_1],[2] as [ticker_2],[3] as [ticker_3],[4] as [ticker_4],[5] as [ticker_5],[6] as [ticker_6],[7] as [ticker_7],[8] as [ticker_8]
FROM (
SELECT d.sector, d.sector_char, d.m_ticker, ROW_NUMBER() OVER(PARTITION BY d.sector ORDER BY d.sector) rn
FROM template13_ticker_data d /* OPs Syntax */
-- FROM @tickerData d /* Use this with the proof table variables */
) data
PIVOT (
MAX(m_ticker)
FOR rn IN ( [1],[2],[3],[4],[5],[6],[7],[8])
) as PivotTable
)
, CompanyBySector as
(
-- You must specify the fixed number of columns in the output
SELECT sector,[1] as [company_1],[2] as [company_2],[3] as [company_3],[4] as [company_4],[5] as [company_5],[6] as [company_6],[7] as [company_7],[8] as [company_8]
FROM (
SELECT d.sector, v.company_name, ROW_NUMBER() OVER(PARTITION BY d.sector ORDER BY d.sector) rn
FROM template13_ticker_data d /* OPs Syntax */
-- FROM @tickerData d /* Use this with the proof table variables */
INNER JOIN template13_vw v /* OPs Syntax */
-- INNER JOIN @Company v /* Use this with the proof table variables */
ON d.m_ticker = v.m_ticker
) data
PIVOT (
MAX(company_name)
FOR rn IN ( [1],[2],[3],[4],[5],[6],[7],[8])
) as PivotTable
)
SELECT TickersBySector.sector, sector_char
,[ticker_1], [company_1]
,[ticker_2], [company_2]
,[ticker_3], [company_3]
,[ticker_4], [company_4]
,[ticker_5], [company_5]
,[ticker_6], [company_6]
,[ticker_7], [company_7]
,[ticker_8], [company_8]
FROM TickersBySector
INNER JOIN CompanyBySector ON TickersBySector.sector = CompanyBySector.sector