Sql 将多行/列透视为一行

Sql 将多行/列透视为一行,sql,pivot,multiple-columns,rows,Sql,Pivot,Multiple Columns,Rows,我们需要获取多行和多列,并将它们转换为每个键一行。我有一个pivot查询,但它不工作。关于定义不明确的列,我遇到了一些错误' 我们的数据如下所示: SECTOR TICKER COMPANY ----------------------------------------------------- 5 ADNT Adient PLC 5 AUTO Autobytel Inc. 5 THRM Gentherm Inc 5

我们需要获取多行和多列,并将它们转换为每个键一行。我有一个pivot查询,但它不工作。关于定义不明确的列,我遇到了一些错误'

我们的数据如下所示:

SECTOR   TICKER  COMPANY
-----------------------------------------------------
5         ADNT    Adient PLC
5         AUTO    Autobytel Inc.
5         THRM    Gentherm Inc
5         ALSN    Allison Transmission Holdings, Inc.
5         ALV     Autoliv, Inc.
12        HES     Hess Corporation
12        AM      Antero Midstrm
12        PHX     Panhandle Royalty Company
12        NBR     Nabors Industries Ltd.
12        AMRC     Ameresco, Inc.
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
我们需要的是每个ID 1行,每个股票代码/公司在不同的列中。因此,输出将如下所示:

5 ADNT   Adient PLC   AUTO  Autobytel Inc.   THRM  Gentherm Inc........
你明白了。每个ID 1行,每个ID在其自己的列中有一个值。我尝试的查询是:

SELECT sector, ticker, company_name
FROM (SELECT d.sector, d.ticker, v.company_name, ROW_NUMBER() OVER(PARTITION BY d.sector ORDER BY d.sector) rn
           FROM template13_ticker_data d, template13_vw v
           WHERE d.m_ticker = v.m_ticker) 
PIVOT (MAX(sector) AS sector, MAX(ticker) AS ticker, MAX(company_name) AS company_name
 FOR (rn) IN (1 AS sector, 2 AS ticker, 3 AS company_name))
ORDER BY sector;

关于数据透视,首先要了解的是,在结果集中选择一列作为数据透视锚点,数据将围绕该轴旋转,这在FOR子句中指定

您只能为单个列透视,但您可以在子查询中或从联接或视图中构造此列作为目标数据查询,OP使用了ROW_NUMBER,但您可以使用任何希望的SQL机制,甚至CASE语句来构建自定义列,以便在数据集中没有可使用的自然列时进行透视

PIVOT将为for列中的每个值创建一列,并为该列提供您指定的聚合函数的值

它有助于可视化构造的记录集,在应用pivot之前,下面的SQL可以重新创建OP提供的数据场景。我在这里使用了表变量来代替OPs表和视图

-添加了扇区字符的模板13股票代码数据 声明@tickerData表 扇区INT, 股票代码CHAR4, m_ticker CHAR4, 扇区_char10 -模板13_vw 声明@公司表 m_ticker CHAR4, 股票代码CHAR4, 公司名称:VARCHAR100 插入@tickerData扇区,股票代码 值5,'ADNT' ,5,“自动” ,5,'THRM' ,5,'ALSN' ,5,'ALV' ,12,“他” ,12,'AM' ,12,'PHX' ,12,'NBR' ,12,'AMRC' 插入@Company ticker,Company\u name 值“ADNT”,“Adient PLC” “汽车公司”、“汽车电池公司” “THRM”和“Gentherm公司” “ALSN”和“Allison Transmission Holdings,Inc.” “阿尔夫”、“奥托立夫公司” “HES”、“Hess公司” “上午”和“中段” “PHX”、“Panhandle特许权公司” ,'NBR','Nabors Industries Ltd.' “AMRC”、“Ameresco公司” -只需重新创建一个与给定数据和查询结构匹配的记录集 更新@tickerData SET m_ticker=ticker 更新@Company SET m_ticker=ticker -填充“扇区字符”以显示多个聚合 更新@tickerData SET sector_char='|'+castsector为varchar+'|' -未经验证的数据证明 选择d.section、d.section\u char、d.ticker、v.company\u name、按d.section超额分配的行数、按d.section订单 来自@tickerData d,@Company v 其中,d.m_ticker=v.m_ticker 轴之前的数据如下所示:

SECTOR   TICKER  COMPANY
-----------------------------------------------------
5         ADNT    Adient PLC
5         AUTO    Autobytel Inc.
5         THRM    Gentherm Inc
5         ALSN    Allison Transmission Holdings, Inc.
5         ALV     Autoliv, Inc.
12        HES     Hess Corporation
12        AM      Antero Midstrm
12        PHX     Panhandle Royalty Company
12        NBR     Nabors Industries Ltd.
12        AMRC     Ameresco, Inc.
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  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
由于我们希望从原始行输出、每行的ticker和company中获得多个列输出,因此我们必须使用以下技术之一:

将多列中的值连接到一列中 仅当您可以在需要使用单个值之前轻松拆分这些列,或者不需要处理这些列时才有用,这纯粹是为了可视化。 执行多个PIVOT查询并连接结果 当每列的聚合逻辑不同时,或者您不是简单地将行值转换为列值,而是将多行聚合为单个单元格响应时,这是必需的。 在像这样的场景中,当我们只是转置值,例如,聚合的结果将匹配原始单元格值,我认为这是一个小技巧,但也可能比其他方法的语法更少。 我之所以说hack是因为核心PIVOT逻辑是重复的,这使得随着查询的发展更难维护

在唯一列上执行单个透视,在其他表上联接以构建其他列 这很容易在输出中允许无限数量的额外行。PIVOT解析表的ID,该表包含我们希望在最终结果中显示的多个值。 让我们先看3,因为这演示了单个透视以及如何为每个透视结果包含多个列:

在这个示例中,我允许每个扇区最多有8个结果,需要注意的是,必须指定透视中的所有输出列,它不是动态的

您可以使用动态查询来测试所需的最大列数,并根据这些结果生成以下查询

还要注意的是,在这个解决方案中,我们不需要在PIVOT源查询中的template13_vw表上进行联接,而是在结果上进行联接,这就是为什么PIVOT返回m_ticker的原因,我假设m_ticker是键,而不是最终结果中显示的ticker

-注意:在这里使用CTE,您可以使用表变量、临时表或您需要的任何其他内容 ;有滴答声 扇区INT, 股票代码CHAR4, m_ticker CHAR4, 扇区_char10 -模板13_vw 声明@公司表 m_ticker CHAR4, 股票代码CHAR4, 公司名称:VARCHAR100 插入@tickerData扇区,股票代码 值5,'ADNT' ,5,“自动” ,5,'THRM' ,5,'ALSN' ,5,'ALV' ,12,“他” ,12,'AM' ,12,'PHX' ,12,'NBR' ,12,'AMRC' 插入@Company ticker,Company\u name 值“ADNT”,“Adient PLC” “汽车公司”、“汽车电池公司” “THRM”和“Gentherm公司” “ALSN”和“Allison Transmission Holdings,Inc.” “阿尔夫”、“奥托立夫公司” “HES”、“Hess公司” “上午”和“中段” “PHX”、“Panhandle特许权公司” ,'NBR','Nabors Industries Ltd.' “AMRC”、“Ameresco公司” -只需重新创建一个与给定数据和查询结构匹配的记录集 更新@tickerData SET m_ticker=ticker 更新@Company SET m_ticker=ticker -填充“扇区字符”以显示多个聚合 更新@tickerData SET sector_char='|'+castsector为varchar+'|' -未经验证的数据证明 选择d.section、d.section\u char、d.ticker、v.company\u name、按d.section超额分配的行数、按d.section订单 来自@tickerData d,@Company v 其中,d.m_ticker=v.m_ticker 轴之前的数据如下所示:

SECTOR   TICKER  COMPANY
-----------------------------------------------------
5         ADNT    Adient PLC
5         AUTO    Autobytel Inc.
5         THRM    Gentherm Inc
5         ALSN    Allison Transmission Holdings, Inc.
5         ALV     Autoliv, Inc.
12        HES     Hess Corporation
12        AM      Antero Midstrm
12        PHX     Panhandle Royalty Company
12        NBR     Nabors Industries Ltd.
12        AMRC     Ameresco, Inc.
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  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
由于我们希望从原始行输出、每行的ticker和company中获得多个列输出,因此我们必须使用以下技术之一:

将多列中的值连接到一列中 仅当您可以在需要使用单个值之前轻松拆分这些列,或者不需要处理这些列时才有用,这纯粹是为了可视化。 执行多个PIVOT查询并连接结果 当每列的聚合逻辑不同时,或者您不是简单地将行值转换为列值,而是将多行聚合为单个单元格响应时,这是必需的。 在像这样的场景中,当我们只是转置值,例如,聚合的结果将匹配原始单元格值,我认为这是一个小技巧,但也可能比其他方法的语法更少。 我之所以说hack是因为核心PIVOT逻辑是重复的,这使得随着查询的发展更难维护

在唯一列上执行单个透视,在其他表上联接以构建其他列 这很容易在输出中允许无限数量的额外行。PIVOT解析表的ID,该表包含我们希望在最终结果中显示的多个值。 让我们先看3,因为这演示了单个透视以及如何为每个透视结果包含多个列:

在这个示例中,我允许每个扇区最多有8个结果,需要注意的是,必须指定透视中的所有输出列,它不是动态的

您可以使用动态查询来测试所需的最大列数,并根据这些结果生成以下查询

还要注意的是,在这个解决方案中,我们不需要在PIVOT源查询中的template13_vw表上进行联接,而是在结果上进行联接,这就是为什么PIVOT返回m_ticker的原因,我假设m_ticker是键,而不是最终结果中显示的ticker

-注意:在这里使用CTE,您可以使用表变量、临时表或您需要的任何其他内容 ;以TickersBySector为例 -必须在输出中指定固定的列数 选择扇区,扇区字符[1]为[m_ticker_1],[2]为[m_ticker_2],[3]为[m_ticker_3],[4]为[m_ticker_4],[5]为[m_ticker_5],[6]为[m_ticker_6],[7]为[m_ticker_7],[8]为[m_ticker_8] 从…起 选择d.section、d.section\u char、d.m\u ticker、按d.section超额分配的行数、按d.section顺序 来自模板13_ticker_data d/*OPs语法*/ -在@tickerData d/*中,将其与验证表变量一起使用*/ 数据 支点 最大自动售票机 对于[1]、[2]、[3]、[4]、[5]、[6]、[7]、[8]中的rn 作为数据透视表 -要与验证表变量一起使用,请将“template13_vw”替换为“@Company” 选择扇区,扇区\字符 ,c1.【股票代码】为【股票代码1】,c1.公司名称为【公司代码1】 ,c2.[股票代码]为[股票代码2],c2.公司名称为[公司代码2] ,c3.【股票代码】为【股票代码3】,c3.公司名称为【公司代码3】 ,c4.【股票代码】为【股票代码4】,c4.公司名称为【公司代码4】 ,c5.【股票代码】为【股票代码5】,c5.公司名称为【公司代码5】 ,c6。[股票代码]为[ticker_6],c6.公司名称为[company_6] ,c7.[ticker]as[ticker_7],c7.公司名称as[company_7] ,c8.[ticker]as[ticker_8],c8.company_name as[company_8] 来自TickersBySector c1.m\U ticker上的左侧外部联接模板13\U vw c1=TickerBySector.m\U ticker\U 1 c2.m_ticker上的左外连接模板13_vw c2=TickerBySector.m_ticker_2 c3.m_报价器上的左外连接模板13_vw c3