SQL 将行值转换为列 headers
SQL convert row values to column headers
我有以下 table:
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 显示为列 headers,然后值将显示 tableA_id 条目是否包含该代码代码字段。所以像这样:
+-----------+------------------------------+
| tableA_id | code A | code B | code C |
+-----------+------------------------------+
| 1 | yes | | |
| 2 | | yes | yes |
| 3 | yes | yes | yes |
etc...
你能在 SQL 中做到这一点吗?
使用条件聚合(在不同方言之间可移植):
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
...
您在 SQL 语法中需要这样的东西
Select *
From Table1
pivot ( Aggregate function For Column Name in ([CodeA], [CodeB] , [CodeC])) as PivotTable
或者,如果您想要一个动态的 SQL 语句,您可以试试下面的方法。
您只需更改 table and/or 列的名称。
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;
/
我有以下 table:
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 显示为列 headers,然后值将显示 tableA_id 条目是否包含该代码代码字段。所以像这样:
+-----------+------------------------------+
| tableA_id | code A | code B | code C |
+-----------+------------------------------+
| 1 | yes | | |
| 2 | | yes | yes |
| 3 | yes | yes | yes |
etc...
你能在 SQL 中做到这一点吗?
使用条件聚合(在不同方言之间可移植):
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
...
您在 SQL 语法中需要这样的东西
Select *
From Table1
pivot ( Aggregate function For Column Name in ([CodeA], [CodeB] , [CodeC])) as PivotTable
或者,如果您想要一个动态的 SQL 语句,您可以试试下面的方法。 您只需更改 table and/or 列的名称。
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;
/