将多行列值显示为单行,多列值

3

我需要在单行中展示一个人的多个收入、收入类型和雇主名称值。例如,如果'A'从三个不同的来源获得了三种不同的收入,

 id  | Name | Employer     |  IncomeType       | Amount

 123 |  XYZ | ABC.Inc      |   EarningsformJob |  $200.00

 123 |  XYZ | Self         | Self Employment   |  $300.00

 123 | XYZ. |  ChildSupport|   Support         |  $500.00

我需要将它们展示为:
 id | Name | Employer1 | Incometype1| Amount1 | Employer2 | incometype2 | Amount2| Employer3 | Incometype3| Amount3.....

 123 |XYZ | ABC.Inc |EarningsformJob |  $200.00|Self  | Self Employment  |  $300.00|ChildSupport|   Support |  $500.00.....

我需要既有“固定列数”(我们知道雇主、收入类型和金额列将重复多少次)的逻辑,也需要“动态显示列”(这些列将重复未知次数)的逻辑。
谢谢。

我认为你可以在这里提供更多信息,例如解决问题的任何初始尝试。我还会确保你使用了你正在使用的关系型数据库标签,因为这段代码可能非常特定于某个引擎。 - Steph Locke
尝试为客户在Sql Server中生成报告。 - user2501777
可能是重复问题:如何在单行中显示多个列的值? - Ken White
1个回答

13

如果你正在使用SQL Server,那么有几种方法可以将数据行转置为列。

聚合函数 / CASE: 你可以使用一个带有CASE表达式的聚合函数和row_number()。这个版本需要你知道要变成列的值的数量:

select id,
  name,
  max(case when rn = 1 then employer end) employer1,
  max(case when rn = 1 then IncomeType end) IncomeType1,
  max(case when rn = 1 then Amount end) Amount1,
  max(case when rn = 2 then employer end) employer2,
  max(case when rn = 2 then IncomeType end) IncomeType2,
  max(case when rn = 2 then Amount end) Amount2,
  max(case when rn = 3 then employer end) employer3,
  max(case when rn = 3 then IncomeType end) IncomeType3,
  max(case when rn = 3 then Amount end) Amount3
from
(
  select id, name, employer, incometype, amount,
    row_number() over(partition by id order by employer) rn
  from yourtable
) src
group by id, name;

请查看带演示的SQL FiddlePIVOT/UNPIVOT: 您可以使用UNPIVOT和PIVOT函数来获得结果。 UNPIVOT将您的多列EmployerIncomeTypeAmount转换为多行,然后应用PIVOT。 假设您知道值的数量并且使用SQL Server 2005+,则可以使用带有UNION ALL的CROSS APPLY来进行UNPIVOT。
select id, name, 
  employer1, incometype1, amount1,
  employer2, incometype2, amount2,
  employer3, incometype3, amount3
from
(
  select id, name, col+cast(rn as varchar(10)) col, value
  from
  (
    select id, name, employer, incometype, amount,
      row_number() over(partition by id order by employer) rn
    from yourtable
  ) t
  cross apply
  (
    select 'employer', employer union all
    select 'incometype', incometype union all
    select 'amount', cast(amount as varchar(50))
  ) c (col, value)
) src
pivot
(
  max(value)
  for col in (employer1, incometype1, amount1,
              employer2, incometype2, amount2,
              employer3, incometype3, amount3)
) piv;

请查看带演示的SQL Fiddle

动态版本:最后,如果你有未知数量的值,则需要使用动态SQL生成结果。

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT ',' + QUOTENAME(col+cast(rn as varchar(10))) 
                    from
                    (
                      select row_number() over(partition by id order by employer) rn
                      from yourtable
                    ) d
                    cross apply
                    ( 
                      select 'employer', 1 union all
                      select 'incometype', 2 union all
                      select 'amount', 3
                    ) c (col, so)
                    group by col, rn, so
                    order by rn, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT id, name,' + @cols + ' 
             from 
             (
                select id, name, col+cast(rn as varchar(10)) col, value
                from
                (
                  select id, name, employer, incometype, amount,
                    row_number() over(partition by id order by employer) rn
                  from yourtable
                ) t
                cross apply
                (
                  select ''employer'', employer union all
                  select ''incometype'', incometype union all
                  select ''amount'', cast(amount as varchar(50))
                ) c (col, value)
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + ')
            ) p '

execute(@query);

请查看带演示的SQL Fiddle。所有版本都会给出结果:

|  ID | NAME | EMPLOYER1 |     INCOMETYPE1 | AMOUNT1 |    EMPLOYER2 | INCOMETYPE2 | AMOUNT2 | EMPLOYER3 |     INCOMETYPE3 | AMOUNT3 |
-------------------------------------------------------------------------------------------------------------------------------------
| 123 |  XYZ |   ABC.Inc | EarningsformJob |     200 | ChildSupport |     Support |     500 |      Self | Self Employment |     300 |

你好 @bluefeet。我使用了你分享的方法。我遇到了我在这里发布的问题。你能帮忙吗?https://dev59.com/LYfca4cB1Zd3GeqPhlz9 - Etibar - a tea bar

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接