替代多个SQL自联接来转换表

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了替代多个SQL自联接来转换表相关的知识,希望对你有一定的参考价值。

目前,我正在使用内部联接多次将表与其自身联接,以将表从每个ID的多行转换为每个ID的一行。我遇到了性能问题,因为我在速度较慢的服务器上针对自己连接了一个较大的表6次。

这是我当前正在使用的查询的简化示例:

SELECT T1.id, T1.value AS 'report', T2.value AS 'area', T3.value AS 'reason', T4.value AS 'maincause' 
FROM data_table T1 
INNER JOIN data_table T2 on T1.id = T2.id AND T2.propname = 'area'
INNER JOIN data_table T3 on T1.id = T3.id AND T3.propname = 'reason'
INNER JOIN data_table T4 on T1.id = T4.id AND T4.propname = 'maincause'
WHERE T1.propname = 'report'

要转换此表:

   id    |  propname  |   value             
  ---------------------------------         
  11037  |    area    |    ABC               
  11037  |   reason   |   short               
  11037  |  maincause | electrical
  11037  |   report   |    yes
   7539  |    area    |    DEF
   7539  |   report   |    no
   7539  |  maincause | mechanical
   7539  |   reason   |   motor

为此:

   id   |  report  |  area  | reason |  maincause  
-----------------------------------------------------
 11037  |   yes    |  ABC   |  short |  electrical  
  7539  |   no     |  DEF   |  motor |  mechanical  

与重复将表自身对接相比,有没有更有效的方法?

答案

尝试:

 select 11037 id,    'area' as propname   ,    'ABC'    as value       into #tmp    
union  select   11037  ,   'reason'   ,   'short'               
union  select   11037  ,  'maincause' , 'electrical'
  union  select 11037  ,   'report'   ,    'yes'
   union  select 7539  ,    'area'    ,    'DEF'
   union  select 7539  ,   'report'   ,    'no'
   union  select 7539  ,  'maincause' , 'mechanical'
   union  select 7539  ,   'reason'   ,   'motor'

   select * from #tmp


   -- Pivot table with one row and five columns  
SELECT id,   
[report], [area], [reason], [maincause]  
FROM  
(SELECT id, propname, [value]     
    FROM #tmp) AS SourceTable  
PIVOT  
(  
max([value])  
FOR propname       IN ([report], [area], [reason], [maincause])  
) AS PivotTable;  
另一答案

我会做这样的事情:

select
 t.id
 ,max(t.area) as area
 ,max(t.reason) as reason
 ,max(t.report) as report
from (
select 
t.id
,case when t.propname = 'area' then t.value else null end as area
,case when t.propname = 'reason' then t.value else null end as reason
,case when t.propname = 'report' then t.value else null end as report
from table1 as t
) as t
group by
t.id

请参见SQL Fiddle中的示例

以上是关于替代多个SQL自联接来转换表的主要内容,如果未能解决你的问题,请参考以下文章

如何改进包含存储过程使用的多个自联接的视图

SQL Server 递归自联接

了解在 SQL 查询的自联接中使用“Between”条件时的逻辑查询处理

sql 日期转换代码片段 - Dato,120,konvertere

Oracle DB 使用连接显示多个表中的数据

oracle 进阶之model子句