问题
Consider the following table:
+------------------------------------------------------------------------------+
| GUID | DeviceGUID | DetailGUID | sValue | iValue | gValue | DateStored |
| ENTRY1 | DEVICE1 | Detail1 | SN112 | | | 01/01/2020 |
| ENTRY2 | DEVICE1 | Detail4 | | 1241 | | 01/01/2020 |
| ENTRY3 | DEVICE1 | Detail7 | | | GUID12 | 01/01/2020 |
| ENTRY4 | DEVICE2 | Detail1 | SN111 | | | 01/01/2020 |
| ENTRY5 | DEVICE2 | Detail2 | RND123 | | | 01/01/2020 |
| ENRTY6 | DEVICE2 | Detail4 | | 2351 | | 03/01/2020 |
| ENTRY7 | DEVICE3 | Detail1 | SN100 | | | 02/01/2020 |
| [...] | [...] | [...] | | | | |
| | | | | | | |
+------------------------------------------------------------------------------+
I have a table which links a DeviceGUID with a DetailsGUID, with the idea of having unlimited options for Details (just create a new detail and it will be fetchable). however, this means I have a finite and unknown amount of records per deviceGUID.
What I want to show to my users is a table like this:
+--------+---------------------------------------------------------------------+
| GUID | DeviceGUID |Detail1 |Detail2 |Detail4 |Detail7 |DateStored |
| ENTRY1 | DEVICE1 |SN112 | [NULL] |1241 |GUID12 | [MAX DateStored] |
| ENTRY2 | DEVICE2 |SN111 | RND123 |2351 | [NULL] | [MAX DateStored] |
| ENTRY3 | DEVICE3 |SN100 | | | | |
| [...] | [...] | | | | | |
+------------------------------------------------------------------------------+
I have been searching a bit and found the PIVOT option but that only seems to function for one field,
another option was CROSS APPLY, but that (seems to) need to convert everything to the same datatype; as I hope is visible n the ColumnNames, I will have 3 types of data: String (VARCHAR) value, Integer value, GUID (uniqueidentifier) value, and they will not be interchangeable (meaning Detail with GUID Detail1 will always have a VARCHAR, Detail with DetailGUID Detail4 will always be an Integer
what I was able to find out until now:
DECLARE @columns NVARCHAR(MAX), @sql NVARCHAR(MAX);
SET @columns = N'';
SELECT @columns+=N', p.'+QUOTENAME([Name])
FROM
(
SELECT GUID AS [Name]
FROM [dbo].Details AS p
) AS x;
SET @sql = N'
SELECT [DeviceObjectGUID], '+STUFF(@columns, 1, 2, '')+' FROM (
SELECT [DeviceObjectGUID], [DateStored], [DetailGUID] as [Name]
FROM [dbo].[DeviceDetails]) AS j PIVOT (MAX(DateStored) FOR [Name] in
('+STUFF(REPLACE(@columns, ', p.[', ',['), 1, 1, '')+')) AS p;';
EXEC sp_executesql @sql
to make a dynamic PIVOT for transposing the data.. but as mentioned this is limited to one column
and
select DeviceObjectGUID, value
from DeviceDetails
cross apply
(
select 'sValue', cast(sValue as varchar(MAX)) union all
select 'gValue', cast(gValue as varchar(MAX))union all
select 'iValue', cast(iValue as varchar(MAX))
) c(col, value)
This will have me converting all fields to VARCHAR..
One other option I tried (to understand PIVOT) was this:
SELECT *
FROM
(SELECT *
FROM [dbo].[DeviceDetails]
) AS SourceTable
PIVOT(
max(sValue)FOR [DetailGUID] IN(
[450533BB-43B2-499B-B2F7-094BFAE949B0],
[7483E518-EB61-4B72-93F7-0F97BBFAFA01],
[29B1BDE8-3AD4-4576-8B76-3CAE83E10B11],
[5FC8CC76-12EB-4924-9320-5D09BBE97C10],
[789AA79B-B1DF-4BA2-860A-7129B39D341F],
[C90F4EFE-D848-4BAB-96BF-8DC6BF4F6E62],
[EC6A4ED3-1475-4B0A-8E08-B2F4E095622F],
[D442B7CA-5825-49D9-9977-D88770304B57],
[99B70FEE-999B-4D44-83E9-EB8119B15930],
[3F83ED76-8CC3-4B3D-936A-F528DEB6C045]
)
) AS PivotTable;
(The GUIDS in the 'IN clause are the DetailGUIDs)
this almost gets me what I want, except that it is not dynamic and the fact that it is still limited to one data column. (max(sValue)) in this case.
===================
in response to
回答1:
It should be as simple as that:
SELECT *
FROM
(
SELECT DeviceGUID
,DetailGUID
,CONCAT(sValue, iValue, gValue) as [value]
,DateStored
FROM my_table
) DS
PIVOT
(
MAX([value]) FOR DetailGUID IN (......)
) PVT
来源:https://stackoverflow.com/questions/63990368/tsql-convert-rows-per-record-to-columns