How Do I Use PIVOT On This Data:?

2020-03-31 07:00发布

问题:

I have a SQL Server table that looks like this:

RESOURCE |  DESCRIPTION | VALUE
Test A      Name        | Resource A-xyz
Test A   |  Height      | 20
Test A   |  Unit        | ft
Test A   |  Location    | Site 1
Test B   |  Volume      | 30
Test C   |  Width       | 10
Test C   |  Unit        | in

I would like to get it into this format:

RESOURCE | Name           | Height | Unit | Location | Volume | Width
Test A   | Resource A-xyz | 20     | ft   | Site 1   |        |
Test B   |                |        |      |          |  30    |
Test C   |                |        | in   |          |        | 10

One of the issues that I have is that there is no set pattern for description; for example, resource "Test B" might have all of the same descriptions as "Test A", while "Test C", might be missing some, and "Test D" might have a totally different set.

So far Google is suggesting that I want to use a pivot table, but I am still not sure how to do that with the above data.

回答1:

The resulting column list is based on the ordering you provide within the PIVOT:

SELECT *
FROM Table1
PIVOT(MAX(VALUE) FOR DESCRIPTION IN (Name,Height,Unit,Location,Volume,Width))p

Demo: SQL Fiddle

If you have changing values for DESCRIPTION it's worthwhile to build this query dynamically, there are plenty of good examples for 'dynamic pivot' to be found.



回答2:

try this code:

SELECT resource,Name,Height,Unit,Location,Volume,Width
FROM 
#T1 AS SourceTable
PIVOT    
(    
max(value)    
FOR description IN ([Name],[Height],[Unit],[Location],[Volume],[Width])    
) AS PivotTable 
ORDER BY 1


回答3:

If you don't want to hardcode the columns and want to generate same view on the fly, you can use this. This will generate dynamic pivot

CREATE TABLE demo
(
RESOURCE VARCHAR(100),
DESCRIPTION VARCHAR(100), VALUE VARCHAR(100)
)

INSERT INTO demo VALUES
('Test A'   ,  'Name'       , 'Resource A-xyz')
,('Test A'   ,  'Height'      , '20')
,('Test A'   ,  'Unit'     , 'ft')
,('Test A'   ,  'Location'   , 'Site 1')
,('Test B'   ,  'Volume'     , '30')
,('Test C'   ,  'Width'       , '10')
,('Test C'   ,  'Unit'        , 'in')


SELECT DISTINCT DESCRIPTION  INTO #tbl FROM demo
//Get list of values to be pivoted
DECLARE @var NVARCHAR(1000)=''
SELECT @var = @var +', ' + DESCRIPTION FROM #tbl 
SELECT @var = SUBSTRING(@var, 2, LEN(@var))
SELECT @var

DECLARE @query NVARCHAR(2000) = 'SELECT * FROM demo PIVOT(MAX(VALUE) FOR DESCRIPTION IN ('+ @var + '))p'
EXEC sp_executesql @query


回答4:

In the end, I did the following:

  1. Selected all distinct descriptions (more than 70!).
  2. Created a table that had resource and every single distinct description as fields
  3. Populated resource column distinct resource names
  4. Ran a series of updates to populate remaining columns for each distinct resource name.

For example

CREATE TABLE #tb1
(
     [RESOURCE] varchar(100),
     [FIELD1]   varchar(100),
     [FIELD2]   varchar(50),
     .
     .
     .
     [LAST FIELD]  varchar(50),
)

INSERT INTO #tb1 (RESOURCE)
SELECT DISTINCT RESOURCE FROM tb2
ORDER BY Resource ASC

UPDATE #tb1 SET [FIELD1] = (SELECT VALUE FROM tb2 WHERE Resource = #tb1.Resource and  Property = [FIELD1])
.
.
.
UPDATE #tb1 SET [LAST FIELD] = (SELECT VALUE FROM tb2 WHERE Resource = #tb1.Resource and  Property = [LAST FIELD])