在數據庫設計時,有時候為了實現數據規范化的目的,會將屬於同一個人的屬性記錄值改用多條記錄的方式來存儲,顯示時又希望將多個屬性數據合並成一行來顯示,這就是行轉列。
例如:下圖的成績記錄表。

那么行轉列的效率又將如何呢?我試了以下三種方式進行行轉列的測試。測試數據表中的記錄數量為120萬條,字段為10個,測試下來感覺性能還不錯。
一、第一種方式(SQL 2000以后的版本)
--總計120萬記錄
SELECT wbook_no
, MAX(CASE WHEN [COP_G_NO] ='60174257' THEN AR END) "60174257"
, MAX(CASE WHEN [COP_G_NO] ='50165814' THEN AR END) "50165814"
, MAX(CASE WHEN [COP_G_NO] ='10221553' THEN AR END) "10221553"
FROM
(
SELECT [COP_G_NO]
, wbook_no
, SUM(G_QTY * decl_Price) AR
FROM WBK_PDE_LIST
WHERE [COP_G_NO] in('60174257','50165814','10221553')
GROUP BY [COP_G_NO]
, wbook_no
) A
GROUP BY wbook_no

二、第二種方式(SQL 2000以后的版本)
SELECT wbook_no
, SUM(
CASE WHEN [COP_G_NO] ='60174257' THEN G_QTY * decl_Price END) "60174257"
, SUM(
CASE WHEN [COP_G_NO] ='50165814' THEN G_QTY * decl_Price END) "50165814"
, SUM(
CASE WHEN [COP_G_NO] ='10221553' THEN G_QTY * decl_Price END) "10221553"
FROM WBK_PDE_LIST
WHERE 1=1
and [COP_G_NO] in('60174257','50165814','10221553')
GROUP BY wbook_no

三、第三種方式:使用PIVOT命令來實現(SQL 2005以后的版本才提供以命令)
SELECT WBOOK_NO
, "60174257"
, "50165814"
, "10221553"
FROM
(
SELECT [COP_G_NO]
, WBOOK_NO
, G_QTY * decl_Price AR
FROM WBK_PDE_LIST
WHERE 1=1
AND [COP_G_NO] in('60174257','50165814','10221553')
)AS D
PIVOT
(
SUM(AR)
FOR [COP_G_NO] in([60174257],[50165814],"10221553")
) AS P

四、以上三種方式的查詢結果都如下:

五、最后我們來比對一下各自性能損耗。從比對結果表來看三者的差別不大,總的來說都在2-3秒之間。
| IO |
CPU |
邏輯讀取 |
物理讀取 |
預讀 |
CPU 時間 |
占用時間 |
||||||
| 表掃描 |
計算標題 |
排序 |
表掃描 |
計算標題 |
排序 |
次 |
次 |
次 |
ms |
ms |
||
| 第一種方式 |
17.652 |
0 |
0.0112513 |
1.33851 |
0.121668 |
0.0131525 |
23827 |
370 |
23827 |
635 |
2216 |
|
| 第二種方式 |
17.652 |
0 |
0.0112513 |
1.33851 |
0.121668 |
0.0131525 |
23827 |
374 |
23827 |
618 |
2171 |
|
| 第三種方式 |
17.652 |
0 |
0.0112513 |
1.33851 |
0.121668 |
0.0131525 |
23827 |
370 |
23827 |
563 |
1960 |
|
