根據伊茨克奔甘在Inside Microsoft SQL Server 2008: T-SQL Querying,unpivoting表時SQL服務器要經歷三個步驟:
- 生成副本
- 提取元素
- 與空值刪除行
步驟1:生成副本
將創建一個虛擬表,其中包含未轉義每列的orignal表中每行的副本。 此外,列名的字符串存儲在新列中(稱爲QuestionName列)。 *注意:我將其中一列的值修改爲NULL,以顯示完整的過程。
UserID UserName AnswerTo1 AnswerToQ2 AnswerToQ3 QuestionName
1 John 1 0 1 AnswerToQuestion1
1 John 1 0 1 AnswerToQuestion2
1 John 1 0 1 AnswerToQuestion3
2 Mary 1 NULL 1 AnswerToQuestion1
2 Mary 1 NULL 1 AnswerToQuestion2
2 Mary 1 NULL 1 AnswerToQuestion3
步驟2:提取元件
然後另一表被創建創建用於從對應 於QuestionName列的字符串值的源列的每個值一個新行。該值存儲在一個新列中(稱爲「響應」列)。
UserID UserName QuestionName Response
1 John AnswerToQuestion1 1
1 John AnswerToQuestion2 0
1 John AnswerToQuestion3 1
2 Mary AnswerToQuestion1 1
2 Mary AnswerToQuestion2 NULL
2 Mary AnswerToQuestion3 1
步驟3:用null
這一步篩選出用在Response列空值創建的任何行的行刪除。換句話說,如果任何的AnswerToQuestion列有空值,它將不會被表示爲未轉義的行。
UserID UserName QuestionName Response
1 John AnswerToQuestion1 1
1 John AnswerToQuestion2 0
1 John AnswerToQuestion3 1
2 Mary AnswerToQuestion1 1
2 Mary AnswerToQuestion3 1
如果遵循這些步驟,你可以
- CROSS JOIN所有表中的行鍼對每個AnswerToQuestion 列名獲得行副本
- 填充的匹配基於 響應列源列和問題名稱
- 刪除空值以獲得與使用UNPIVOT相同的 結果。
一個下面的例子:
DECLARE @t1 TABLE (UserID INT, UserName VARCHAR(10), AnswerToQuestion1 INT,
AnswertoQuestion2 INT, AnswerToQuestion3 INT
)
INSERT @t1 SELECT 1, 'John', 1, 0, 1 UNION ALL SELECT 2, 'Mary', 1, NULL, 1
SELECT
UserID,
UserName,
QuestionName,
Response
FROM (
SELECT
UserID,
UserName,
QuestionName,
CASE QuestionName
WHEN 'AnswerToQuestion1' THEN AnswerToQuestion1
WHEN 'AnswerToQuestion2' THEN AnswertoQuestion2
ELSE AnswerToQuestion3
END AS Response
FROM @t1 t1
CROSS JOIN (
SELECT 'AnswerToQuestion1' AS QuestionName
UNION ALL SELECT 'AnswerToQuestion2'
UNION ALL SELECT 'AnswerToQuestion3'
) t2
) t3
WHERE Response IS NOT NULL
來源
2010-09-10 05:57:54
8kb
我得到'列問題不存在'與此 – hedgedandlevered 2016-12-09 17:38:22
不,我的查詢工作正常。只有在查詢中的其他位置嘗試引用別名'QuestionName'時纔會出現該錯誤。將這個查詢放入派生表中並從中選擇,然後可以在其上添加條件。你正在使用SQL Server,對嗎? – ErikE 2016-12-09 17:50:31
哦,不,我正在使用常規的SQL。沒有看到sql-server標籤。 謝謝,最終找出了使用8kb的答案和你的。 – hedgedandlevered 2016-12-09 18:55:51