Transpone SQL列不会降低性能

时间:2017-04-26 20:39:12

标签: sql-server performance pivot transform

我使用SQL Server 2012.我有两个包含数据的大表,如下所示:

tableProjects(为简单起见,减少了列数)

| ID | Name     |
| 1  | Project1 |
| 2  | Project2 |
| …  | …        |
| N  | ProjectN |

tableHours(为简单起见,处理阶段的数量减少到3个)

| ProjectID | ProcessStage | Hours |
| 1         | 1            | 10    |
| 1         | 2            | 20    |
| 1         | 3            | 30    |
| 2         | 1            | 40    |
| 2         | 2            | 50    |
| 2         | 3            | 60    |
| …         | …            | …     |
| N         | 1            | 70    |
| N         | 2            | 80    |
| N         | 3            | 90    |

我需要以每个ProcessStage获取单独列的方式选择此数据,因此我将这样的数据转发:

SELECT p.ID, p.Name,
(SELECT Hours FROM tableHours WHERE ProcessStage = 1 AND ProjectID = p.ID) AS Hours1,
(SELECT Hours FROM tableHours WHERE ProcessStage = 2 AND ProjectID = p.ID) AS Hours2,
(SELECT Hours FROM tableHours WHERE ProcessStage = 3 AND ProjectID = p.ID) AS Hours3
FROM tableProjects p

事实上,我确实得到了我想要的东西:

| ID | Name     | Hours1 | Hours2 | Hours3 |
| 1  | Project1 | 10     | 20     | 30     |
| 2  | Project2 | 40     | 50     | 60     |
| …  | …        | …      | …      | …      |
| N  | ProjectN | 70     | 80     | 90     |

但在我的情况下,表现非常重要,所以我在想是否有更有效的方式来做到这一点。如果你知道,你能告诉我吗?感谢。

1 个答案:

答案 0 :(得分:1)

使用条件聚合来转移数据:

select 
    p.id
  , p.Name
  , Hours1 = max(case when h.ProcessStage = 1 then h.Hours end) 
  , Hours2 = max(case when h.ProcessStage = 2 then h.Hours end) 
  , Hours3 = max(case when h.ProcessStage = 3 then h.Hours end) 
from tableProjects p
  inner join tableHours h
    on h.Projectid = p.id
group by p.id, p.Name

您可以使用动态sql自动生成数据透视表所需的列,但由于您说性能非常重要,因此最好在可能的情况下对其进行硬编码。