SQL将行值转换为列标题

时间:2016-01-07 12:47:43

标签: sql pivot crosstab

我有下表:

tableA
+-----------+--------+
| tableA_id |  code  |
+-----------+--------+
|         1 | code A |
|         2 | code B |
|         3 | code A |
|         3 | code C |
|         3 | code B |
|         4 | code A |
|         4 | code C |
|         4 | code B |
|         5 | code A |
|         5 | code C |
|         5 | code B |
+-----------+--------+

我想使用查询将代码A,代码B,代码C显示为列标题,然后值将显示tableA_id条目是否包含代码字段中的代码。所以像这样:

+-----------+------------------------------+
| tableA_id |  code A |  code B  |  code C |
+-----------+------------------------------+
|         1 |   yes   |          |         |
|         2 |         |   yes    |   yes   |
|         3 |   yes   |   yes    |   yes   |

etc...

你能在SQL中做到这一点吗?

3 个答案:

答案 0 :(得分:4)

使用condtitional聚合(在不同方言之间移植):

SELECT tableA_id,
       MAX(CASE WHEN code ='code A' THEN 'yes' END) AS "code A",
       MAX(CASE WHEN code ='code B' THEN 'yes' END) AS "code B",
       MAX(CASE WHEN code ='code C' THEN 'yes' END) AS "code C"
FROM tableA
GROUP BY tableA_id;

SqlFiddleDemo_MySQL SqlFiddleDemo_Postgresql

输出:

╔════════════╦═════════╦═════════╦════════╗
║ tableA_id  ║ code A  ║ code B  ║ code C ║
╠════════════╬═════════╬═════════╬════════╣
║         1  ║ yes     ║ (null)  ║ (null) ║
║         2  ║ (null)  ║ yes     ║ (null) ║
║         3  ║ yes     ║ yes     ║ yes    ║
║         4  ║ yes     ║ yes     ║ yes    ║
║         5  ║ yes     ║ yes     ║ yes    ║
╚════════════╩═════════╩═════════╩════════╝

有很多可能性(搜索):

PIVOT            -> SQL Server/Oracle
CROSSTAB         -> Postgresql
SELF OUTER JOIN  -> All
CONDITIONAL AGG  -> All
...

答案 1 :(得分:0)

在SQL语法

中你需要这样的东西
Select *
From Table1
pivot ( Aggregate function For Column Name in ([CodeA], [CodeB] , [CodeC])) as PivotTable

答案 2 :(得分:0)

或者,如果您需要动态SQL语句,可以尝试以下方法。 您只需要更改表和/或列的名称。

declare
cursor code is select code, rownum rn, count(*) over (partition by 1 ) as cnt from (select distinct code from test) order by 1;
build_Case clob;
a varchar2(100);
begin

for i in code loop
if i.rn <> i.cnt then
build_case := build_case || CHR(10) || ' max((case when code = ''' || i.code || ''' then ''yes'' else null end)) ' || i.code || ',';
else 
build_case := build_case || CHR(10) || ' max((case when code = ''' || i.code || ''' then ''yes'' else null end)) ' || i.code;
end if;
end loop;

build_case := 'select id,' || build_case || ' from test group by id';
dbms_output.put_line(build_Case);

--execute immediate build_Case;
end;
/