San*_*dro 12 sql sql-server unpivot
我有一个这种结构的表.
UserID | UserName | AnswerToQuestion1 | AnswerToQuestion2 | AnswerToQuestion3
1 | John | 1 | 0 | 1
2 | Mary | 1 | 1 | 0
Run Code Online (Sandbox Code Playgroud)
我无法弄清楚我将使用什么SQL查询来获取这样的结果集:
UserID | UserName | QuestionName | Response
1 | John | AnswerToQuestion1 | 1
1 | John | AnswerToQuestion2 | 0
1 | John | AnswerToQuestion3 | 1
2 | Mary | AnswerToQuestion1 | 1
2 | Mary | AnswerToQuestion2 | 1
2 | Mary | AnswerToQuestion3 | 0
Run Code Online (Sandbox Code Playgroud)
我正在尝试将三列分成三个单独的行.这可能吗?
SELECT
Y.UserID,
Y.UserName,
QuestionName = 'AnswerToQuestion' + X.Which,
Response =
CASE X.Which
WHEN '1' THEN AnswerToQuestion1
WHEN '2' THEN AnswerToQuestion2
WHEN '3' THEN AnswerToQuestion3
END
FROM
YourTable Y
CROSS JOIN (SELECT '1' UNION ALL SELECT '2' UNION ALL SELECT '3') X (Which)
Run Code Online (Sandbox Code Playgroud)
这对UNPIVOT(有时更好)也同样有效,并且也适用于SQL 2000.
我利用问题的相似性来创建QuestionName列,但当然这将适用于不同的问题名称.
请注意,如果您的问题清单长或者问题名称较长,则可能是2列X平台,一个问题号和一个用于问题名称实验.或者,如果您已经有一个包含问题列表的表格,那么CROSS就会加入.如果某些问题是NULL,那么最简单的方法是将上述查询放在CTE或派生表中,然后添加WHERE Response IS NOT NULL.
根据Itzik Ben-Gan在Inside Microsoft SQL Server 2008:T-SQL查询中,SQL Server在解开表格时会经历三个步骤:
- 生成副本
- 提取元素
- 删除带有NULL的行
第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
Run Code Online (Sandbox Code Playgroud)
第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
Run Code Online (Sandbox Code Playgroud)
第3步:使用NULLS删除行
此步骤筛选出在"响应"列中使用空值创建的所有行.换句话说,如果任何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
Run Code Online (Sandbox Code Playgroud)
如果您按照这些步骤操作,则可以
以下示例:
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
Run Code Online (Sandbox Code Playgroud)
假设SQL Server 2005+,您可以使用UNPIVOT
;with YourTable as
(
SELECT 1 UserID,'John' UserName,1 AnswerToQuestion1,0 AnswerToQuestion2,1 AnswerToQuestion3
UNION ALL
SELECT 2, 'Mary', 1, 1, 0
)
SELECT UserID, UserName, QuestionName, Response
FROM YourTable
UNPIVOT
(Response FOR QuestionName IN
(AnswerToQuestion1, AnswerToQuestion2,AnswerToQuestion3)
)AS unpvt;
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
15574 次 |
| 最近记录: |