SQL 多个值的数据透视
SQL Pivot for multiple values
这是我的数据
Product_ID Question Answer
1 When Monday
1 Where Home
1 Where Work
1 How Car
2 When saturday
2 Where Home
2 Where Church
2 How Bus
2 How Walk
我希望数据显示如下
Product_ID When Where How
1 Monday Home Car
1 Monday Work Car
2 Saturday Home Bus
2 Saturday Church Bus
2 Saturday Home Walk
2 Saturday Church Walk
但我只能旋转数据并且能够获得以下样式
Product_ID When Where
1 Monday Work
2 Saturday Home
使用以下查询
select * from
(
select product_ID,question,answer from table1
) src
pivot (
max(answer)
for question in ([when],[where])
)piv
如评论中所述,这实际上并不需要 PIVOT。实现预期结果的一种方法(假设只有两个问题:'when' 和 'where')是使用带有子查询的自连接:
SELECT T1.Product_ID, T1.[When], T2.[Where]
FROM (
SELECT Product_ID, Answer [When]
FROM table1
WHERE Question = 'When'
) T1
JOIN (
SELECT Product_ID, Answer [Where]
FROM table1
WHERE Question = 'Where') T2 ON T2.Product_ID = T1.Product_ID;
或者,使用 APPLY 来实现相同的目的:
SELECT *
FROM (
SELECT Product_ID, Answer [When]
FROM table1
WHERE Question = 'When'
) T1
CROSS APPLY (
SELECT Answer [Where]
FROM table1
WHERE Product_ID = T1.Product_ID
AND Question = 'Where') T2;
编辑:这是使用动态 SQL 实现预期结果的一种方法:
/* -- Sample data
CREATE TABLE table1 (Product_ID INT NOT NULL, Question VARCHAR(20) NOT NULL, Answer VARCHAR(20) NOT NULL);
INSERT table1
VALUES (1, 'When', 'Monday')
, (1, 'Where', 'Home')
, (1, 'Where', 'Work')
, (1, 'How', 'Car')
, (2, 'When', 'Saturday')
, (2, 'Where', 'Home')
, (2, 'Where', 'Church')
, (2, 'How', 'Bus')
, (2, 'How', 'Walk')
, (3, 'Where', 'Park'); -- No other questions for this Product_ID
*/
DECLARE @SQL VARCHAR(MAX) = '', @cols VARCHAR(MAX) = '', @joins VARCHAR(MAX) = '', @coalesce VARCHAR(MAX) = 'COALESCE';
SELECT @coalesce += CASE RN WHEN 1 THEN '(' ELSE ',' END + 'T' + CAST(RN AS VARCHAR(4)) + '.Product_ID'
, @cols += ', T' + CAST(RN AS VARCHAR(4)) + '.' + QUOTENAME(Question)
, @joins +=
CASE RN
WHEN 1
THEN '
FROM (SELECT Product_ID, Answer ' + QUOTENAME(Question) + ' FROM table1 WHERE Question = ''' + Question + ''') T1 '
ELSE '
FULL JOIN (SELECT Product_ID, Answer ' + QUOTENAME(Question) + ' FROM table1 WHERE Question = ''' + Question + ''') T' + CAST(RN AS VARCHAR(4)) + ' ON T' + CAST(RN AS VARCHAR(4)) + '.Product_ID = T1.Product_ID'
END
FROM (SELECT Question, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN FROM (SELECT DISTINCT Question FROM table1) T) T
ORDER BY RN;
SELECT @coalesce += ') Product_ID';
SELECT @SQL = 'SELECT ' + @coalesce + @cols + @joins;
PRINT @SQL;
EXEC(@SQL);
这是我的数据
Product_ID Question Answer
1 When Monday
1 Where Home
1 Where Work
1 How Car
2 When saturday
2 Where Home
2 Where Church
2 How Bus
2 How Walk
我希望数据显示如下
Product_ID When Where How
1 Monday Home Car
1 Monday Work Car
2 Saturday Home Bus
2 Saturday Church Bus
2 Saturday Home Walk
2 Saturday Church Walk
但我只能旋转数据并且能够获得以下样式
Product_ID When Where
1 Monday Work
2 Saturday Home
使用以下查询
select * from
(
select product_ID,question,answer from table1
) src
pivot (
max(answer)
for question in ([when],[where])
)piv
如评论中所述,这实际上并不需要 PIVOT。实现预期结果的一种方法(假设只有两个问题:'when' 和 'where')是使用带有子查询的自连接:
SELECT T1.Product_ID, T1.[When], T2.[Where]
FROM (
SELECT Product_ID, Answer [When]
FROM table1
WHERE Question = 'When'
) T1
JOIN (
SELECT Product_ID, Answer [Where]
FROM table1
WHERE Question = 'Where') T2 ON T2.Product_ID = T1.Product_ID;
或者,使用 APPLY 来实现相同的目的:
SELECT *
FROM (
SELECT Product_ID, Answer [When]
FROM table1
WHERE Question = 'When'
) T1
CROSS APPLY (
SELECT Answer [Where]
FROM table1
WHERE Product_ID = T1.Product_ID
AND Question = 'Where') T2;
编辑:这是使用动态 SQL 实现预期结果的一种方法:
/* -- Sample data
CREATE TABLE table1 (Product_ID INT NOT NULL, Question VARCHAR(20) NOT NULL, Answer VARCHAR(20) NOT NULL);
INSERT table1
VALUES (1, 'When', 'Monday')
, (1, 'Where', 'Home')
, (1, 'Where', 'Work')
, (1, 'How', 'Car')
, (2, 'When', 'Saturday')
, (2, 'Where', 'Home')
, (2, 'Where', 'Church')
, (2, 'How', 'Bus')
, (2, 'How', 'Walk')
, (3, 'Where', 'Park'); -- No other questions for this Product_ID
*/
DECLARE @SQL VARCHAR(MAX) = '', @cols VARCHAR(MAX) = '', @joins VARCHAR(MAX) = '', @coalesce VARCHAR(MAX) = 'COALESCE';
SELECT @coalesce += CASE RN WHEN 1 THEN '(' ELSE ',' END + 'T' + CAST(RN AS VARCHAR(4)) + '.Product_ID'
, @cols += ', T' + CAST(RN AS VARCHAR(4)) + '.' + QUOTENAME(Question)
, @joins +=
CASE RN
WHEN 1
THEN '
FROM (SELECT Product_ID, Answer ' + QUOTENAME(Question) + ' FROM table1 WHERE Question = ''' + Question + ''') T1 '
ELSE '
FULL JOIN (SELECT Product_ID, Answer ' + QUOTENAME(Question) + ' FROM table1 WHERE Question = ''' + Question + ''') T' + CAST(RN AS VARCHAR(4)) + ' ON T' + CAST(RN AS VARCHAR(4)) + '.Product_ID = T1.Product_ID'
END
FROM (SELECT Question, ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) RN FROM (SELECT DISTINCT Question FROM table1) T) T
ORDER BY RN;
SELECT @coalesce += ') Product_ID';
SELECT @SQL = 'SELECT ' + @coalesce + @cols + @joins;
PRINT @SQL;
EXEC(@SQL);