在不损失性能的情况下转置 SQL 列

Transpone SQL columns without loss in performance

我用的是SQLServer 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    |

我需要 select 这些数据,每个 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     |

但在我的案例中,性能非常重要,所以我在考虑是否有更高效的方法来做到这一点。如果你知道,你能告诉我吗?谢谢。

使用条件聚合来透视数据:

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 自动生成数据透视表所需的列,但既然您说性能非常重要,那么最好尽可能对其进行硬编码。