Cannot pivot table with my query?

走远了吗. 提交于 2020-01-05 07:58:07

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!