简体   繁体   English

将SQL表从行展平为列,从而允许多个结果

[英]Flatten a SQL Table from rows to columns allowing multiple results

I have an issue that is like a non-aggregating pivot, but I want my table to include multiple results. 我有一个问题,就像一个非聚合的数据透视表,但我希望我的表包含多个结果。 As an example I start out like this: 作为一个例子,我开始这样:

ID | OrganizationID | Group | Vendor | Product 
 1         3            G1      V1       P1
 2         3            G1      V2       P2
 3         3            G2      V3       P3
 4         4            G1      V1       P1
 5         4            G1      V1       P2

And need my data to end up like this: 并且需要我的数据最终像这样:

ID | OrganizationID | G1_V1 | G1_V2 | G2_V3
 1         3            P1      P2      P3 
 2         4            P1     NULL    NULL
 3         4            P2     NULL    NULL

The data I am working with is around 7 million rows so self-joining with dynamic sql has proven extremely slow. 我正在使用的数据大约有700万行,所以自动加入动态sql已经证明非常慢。 Is there something easy I'm missing? 有什么容易让我失踪吗? Thanks in advance! 提前致谢!

You can use a common table expression and a set of CASE statements to get the pivot structure you need; 您可以使用公用表表达式和一组CASE语句来获取所需的数据透视结构; this will work identically in most RDBMS's. 这在大多数RDBMS中都会完全相同。

WITH cte AS (
  SELECT id, organizationid, 
         CONCAT([Group],'_',Vendor) col, 
         product,
         ROW_NUMBER() OVER (
           PARTITION BY organizationid,[group],vendor 
           ORDER BY product) rn
  FROM myTable
)
SELECT 
  organizationid,
  MAX(CASE WHEN col='G1_V1' THEN product ELSE NULL END) G1_V1,
  MAX(CASE WHEN col='G1_V2' THEN product ELSE NULL END) G1_V2,
  MAX(CASE WHEN col='G2_V3' THEN product ELSE NULL END) G2_V3
FROM cte
GROUP BY organizationid, rn;

...or, alternately, you can use TSQL's regular PIVOT statement to replace the CASE part, which will probably be faster but may not work in all RDBMS's; ...或者,您可以使用TSQL的常规PIVOT语句来替换CASE部分,这可能会更快,但可能无法在所有RDBMS中使用;

WITH cte AS (
  SELECT id, organizationid, 
         CONCAT([Group],'_',Vendor) col, 
         product,
         ROW_NUMBER() OVER (
           PARTITION BY organizationid,[group],vendor 
           ORDER BY product) rn
  FROM myTable
)
SELECT organizationid as organizationid, 
[G1_V1], [G1_V2], [G2_V3]
FROM
(SELECT organizationid,rn,col, product FROM cte) AS SourceTable
PIVOT
(
  MAX(product) FOR col IN ([G1_V1], [G1_V2], [G2_V3])
) AS PivotTable;

An SQLfiddle to test both . 一个SQLfiddle来测试它们

You can produce a similar pivot in PostgreSQL using crosstab , however I don't have a PostgreSQL database with the tablefunc module installed to test on, so can only link to the details. 您可以使用交叉表在PostgreSQL中生成类似的数据透视 ,但是我没有安装了tablefunc模块的PostgreSQL数据库进行测试,因此只能链接到详细信息。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM