问题
I have a table which looks like this -
Id AttributeName AttributeValue
A1 Atr1 A1V1
A1 Atr2 A1V2
A1 Atr3 A1V3
A2 Atr1 A2V1
A2 Atr2 A2V2
A2 Atr3 A3V3
Each ID in this table has the exact same attributes, ie ATR1, ATR2, ATR3. The values of these attributes is unique.
I want to pivot this table and get the following output -
Id Atr1 Atr2 Atr3
A1 A1V1 A1V2 A1V3
A2 A2V1 A2V2 A2V3
How do I do this ?
I tried a query and it failed with the error - Msg 156, Level 15, State 1, Line 21 Incorrect syntax near the keyword 'FOR'.
-- Create a temporary table
DECLARE @MyTable TABLE
(Id varchar(25),
AttributeName varchar(30),
AttributeValue varchar(30))
-- Load Sample Data
INSERT INTO @MyTable VALUES ('A1', 'Atr1', 'A1V1')
INSERT INTO @MyTable VALUES ('A1', 'Atr2', 'A1V2')
INSERT INTO @MyTable VALUES ('A1', 'Atr3', 'A1V3')
INSERT INTO @MyTable VALUES ('A2', 'Atr1', 'A2V1')
INSERT INTO @MyTable VALUES ('A2', 'Atr2', 'A2V2')
INSERT INTO @MyTable VALUES ('A2', 'Atr3', 'A3V3')
SELECT Id, [Atr1], [Atr2],[Atr3]
FROM
(
SELECT ID, AttributeName, AttributeValue
FROM @MyTable) AS SourceTable
PIVOT
(
AttributeValue
FOR AttributeName IN ([ATR1], [ATR2], [ATR3])
) AS pvt
回答1:
Just to expand on the other answers, the PIVOT function requires some type of aggregation. Since the value that you want to convert from a row into a column is a string, then you are limited to using either the max()
or min()
aggregate function.
While @Muhammed Ali's answer will work when you have a single AttributeName
/AttributeValue
pair, if you have multiple pairs for each ID
, then you will only return either the max
or min
value.
For example if your sample data is:
INSERT INTO @MyTable VALUES ('A1', 'Atr1', 'A1V1');
INSERT INTO @MyTable VALUES ('A1', 'Atr1', 'A1V4');
INSERT INTO @MyTable VALUES ('A1', 'Atr2', 'A1V2');
INSERT INTO @MyTable VALUES ('A1', 'Atr3', 'A1V3');
INSERT INTO @MyTable VALUES ('A2', 'Atr1', 'A2V1');
INSERT INTO @MyTable VALUES ('A2', 'Atr2', 'A2V2');
INSERT INTO @MyTable VALUES ('A2', 'Atr3', 'A3V3');
Even though you have multiple rows for the combination of A1
and Atr1
, the other queries are only returning the max(attributevalue)
:
| ID | ATR1 | ATR2 | ATR3 |
|----|------|------|------|
| A1 | A1V4 | A1V2 | A1V3 |
| A2 | A2V1 | A2V2 | A3V3 |
I would guess that you would actually want to return all of the combinations. I suggest expanding your query to include the windowing function, row_number()
in your query. This query generates a unique value that will then be included in the grouping aspect of the PIVOT and will allow you to return more than one row for each ID.
By adding the row_number()
, the query will be similar to the following:
SELECT Id, [Atr1], [Atr2],[Atr3]
FROM
(
SELECT ID, AttributeName, AttributeValue,
row_number() over(partition by id, attributename
order by attributevalue) seq
FROM @MyTable
) AS SourceTable
PIVOT
(
max(AttributeValue)
FOR AttributeName IN ([ATR1], [ATR2], [ATR3])
) AS pvt
order by id;
See SQL Fiddle with Demo. You will get a result that returns all rows:
| ID | ATR1 | ATR2 | ATR3 |
|----|------|--------|--------|
| A1 | A1V1 | A1V2 | A1V3 |
| A1 | A1V4 | (null) | (null) |
| A2 | A2V1 | A2V2 | A3V3 |
If you are having trouble grasping the concept of PIVOT, then I would suggest look at using a combination of an aggregate function with a CASE expression to get the result. You can then see the grouping of the sequence/id:
SELECT Id,
max(case when attributename = 'Atr1' then attributevalue end) Atr1,
max(case when attributename = 'Atr2' then attributevalue end) Atr2,
max(case when attributename = 'Atr3' then attributevalue end) Atr3
FROM
(
SELECT ID, AttributeName, AttributeValue,
row_number() over(partition by id, attributename
order by attributevalue) seq
FROM @MyTable
) AS SourceTable
group by id, seq
See SQL Fiddle with Demo
回答2:
DECLARE @MyTable TABLE
(Id varchar(25),
AttributeName varchar(30),
AttributeValue varchar(30))
-- Load Sample Data
INSERT INTO @MyTable VALUES ('A1', 'Atr1', 'A1V1')
INSERT INTO @MyTable VALUES ('A1', 'Atr2', 'A1V2')
INSERT INTO @MyTable VALUES ('A1', 'Atr3', 'A1V3')
INSERT INTO @MyTable VALUES ('A2', 'Atr1', 'A2V1')
INSERT INTO @MyTable VALUES ('A2', 'Atr2', 'A2V2')
INSERT INTO @MyTable VALUES ('A2', 'Atr3', 'A3V3')
SELECT Id, [Atr1], [Atr2],[Atr3]
FROM
(
SELECT ID, AttributeName, AttributeValue
FROM @MyTable) AS SourceTable
PIVOT
(
MAX(AttributeValue)
FOR AttributeName IN ([ATR1], [ATR2], [ATR3])
) AS pvt
You are missing the function in you Pivot table syntax
Result Set
Id Atr1 Atr2 Atr3
A1 A1V1 A1V2 A1V3
A2 A2V1 A2V2 A3V3
回答3:
Try this:
select id,
max(case AttributeName when 'Atr1' then AttributeName else '' end) as atr1,
max(case AttributeName when 'Atr2' then AttributeName else '' end) as atr2,
max(case AttributeName when 'Atr3' then AttributeName else '' end) as atr3,
AttributeValue
from YourTable
group by id, AttributeValue
order by id
来源:https://stackoverflow.com/questions/20253345/cannot-pivot-table-with-my-query