[SQL] 使用 PIVOT 扭轉資料,由直列轉為橫向資料

面對數筆有意義資料要匯總成橫式資料時,可以考慮使用 PIVOT 來扭轉資料,讓資料呈現上更貼近人性。

前言

筆者目前有個 Lang 資料表用來存放多國語系的顯示文字,專案後期客戶時常會提出想要確認語系翻譯是否適宜,因此以單筆資料包含各語系顯示名稱是較好的呈現方式,所以這時就可以透過 PIVOT 轉置彙整語系資料,再以此格式匯出 Excel 讓用戶校正後再匯入資料庫中,簡單地完成繁雜的校對工作。

 

實際演練

首先來準備一下測試資料

-- create table
CREATE TABLE [dbo].[Lang] (
	[MasterLangId] [INT] NOT NULL
	,[LangType] [NVARCHAR](60) NOT NULL
	,[ShowText] [NVARCHAR](400) NULL
	,[InsertUser] [NVARCHAR](10) NOT NULL
	,[InsertTime] [DATETIME] NOT NULL
	,[UpdateUser] [NVARCHAR](10) NULL
	,[UpdateTime] [DATETIME] NULL
)

-- create data
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (1, N'en-US', N'Link to company type', N'Chris', GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (1, N'zh-CN', N'连结厂商型态', N'Chris', GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (1, N'zh-TW', N'連結廠商型態', N'Chris',GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (2, N'en-US', N'Export', N'Chris', GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (2, N'zh-CN', N'汇出', N'Chris', GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (2, N'zh-TW', N'匯出', N'Chris', GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (3, N'en-US', N'Product Name', N'Chris',GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (3, N'zh-CN', N'产品名称', N'Chris', GETDATE(), N'Chris', GETDATE())
INSERT [dbo].[Lang] ([MasterLangId], [LangType], [ShowText], [InsertUser], [InsertTime], [UpdateUser], [UpdateTime]) VALUES (3, N'zh-TW', N'產品名稱', N'Chris', GETDATE(), N'Chris', GETDATE())

 

以下圖右語法為例,可以看到 PIVOT 語法使用上主要區分為兩個區塊,第一個區塊當然就是撈出所需資料(1+2+3),接著第二區塊則利用 PIVOT 語法設定需匯總的欄位與方式(4),最後設定轉置欄位及其特定資料(5)作為新欄位;執行後成功將個別獨立的資料轉置匯總呈橫向總表囉!細部說明請參考以下資訊:

撈取資料與 PIVOT 設定須包含以下五個部分:

  1. 群組欄位: 可多欄位,會 Group 這些欄位後做為實際輸出的資料量。
  2. 轉置欄位: 轉置後新增欄位出處(就是想顯示匯總的分類條件)
  3. 彙總欄位: 轉置後新增欄位內容(就是想匯總的目標資料)
  4. 設定彙總欄位及方式: 轉置後群組中有可能存在多筆資料,因此需要針對彙總欄位設定彙總方式
  5. 設定轉置後新增欄位: 設定轉置欄位,並指定轉置欄位中需彙總的條件值(置於中括號)作為新欄位。

 

最後執行以下語法就會依此 群組欄位轉置欄位條件來查詢彙總出彙總欄位內容值啦!

SELECT *
FROM (
	SELECT l.MasterLangId, l.LangType, l.ShowText
	FROM dbo.Lang l
) t 
PIVOT (
	-- 設定彙總欄位及方式
	MAX(ShowText) 
	-- 設定轉置欄位,並指定轉置欄位中需彙總的條件值作為新欄位
	FOR LangType IN ([zh-TW], [zh-CN], [en-US])
) p;

 

參考資料

[SQL] PIVOT 和 UNPIVOT

[T-SQL]PIVOT兩欄甚至多欄的方法


希望此篇文章可以幫助到需要的人

若內容有誤或有其他建議請不吝留言給筆者喔 !