TSQL-将每个记录的行转换为列
考虑下表:TSQL-将每个记录的行转换为列,sql,sql-server,tsql,Sql,Sql Server,Tsql,考虑下表: +------------------------------------------------------------------------------+ | GUID | DeviceGUID | DetailGUID | sValue | iValue | gValue | DateStored | | ENTRY1 | DEVICE1 | Detail1 | SN112 | | | 01/01/2020 | |
+------------------------------------------------------------------------------+
| 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 |
| [...] | [...] | [...] | | | | |
| | | | | | | |
+------------------------------------------------------------------------------+
我有一个表,它将DeviceGUID与DetailsGUID链接起来,其思想是拥有无限的细节选项(只需创建一个新的细节,它就可以获取)。但是,这意味着每个设备GUID的记录数量有限且未知
我想向我的用户展示的是这样一个表:
+--------+---------------------------------------------------------------------+
| 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 | | | | |
| [...] | [...] | | | | | |
+------------------------------------------------------------------------------+
我搜索了一下,找到了PIVOT
选项,但它似乎只适用于一个字段,
另一个选项是交叉应用,但(似乎)需要将所有内容转换为相同的数据类型;正如我希望在ColumnNames中可见的那样,我将有3种类型的数据:字符串(VARCHAR
)值、Integer
值、GUID(uniqueidentifier
)值,并且它们不能互换(这意味着带有GUID Detail1的详细信息将始终具有VARCHAR
,带有DetailGUID Detail4的详细信息将始终是整数
直到现在我才发现:
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
创建一个用于转置数据的动态轴心..但如前所述,这仅限于一列
及
这将使我将所有字段转换为VARCHAR
我尝试(理解PIVOT)的另一个选择是:
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;
(在子句中“中的GUID是DetailGUID)
这几乎满足了我的需求,除了它不是动态的,而且在本例中它仍然被限制为一个数据列。(max(sValue)
)
===================
回应
它应该很简单:
SELECT *
FROM
(
SELECT DeviceGUID
,DetailGUID
,CONCAT(sValue, iValue, gValue) as [value]
,DateStored
FROM my_table
) DS
PIVOT
(
MAX([value]) FOR DetailGUID IN (......)
) PVT
CONCAT消除了类型问题;然而,这导致了一个表,每个设备GUID有一个条目,它应该给我的是每个可用的DetailGUID,填充gValue、iValue或sValue——添加了一个带有outputRemove theGUID
列的屏幕截图。似乎就是这样。让我验证一下问题是GUID
使行成为唯一的是的,同样的情况也会发生在DateStored上;这就是为什么我在某些情况下仍然会得到多行,但这似乎是我的数据导入中的一个问题。。。
SELECT *
FROM
(
SELECT DeviceGUID
,DetailGUID
,CONCAT(sValue, iValue, gValue) as [value]
,DateStored
FROM my_table
) DS
PIVOT
(
MAX([value]) FOR DetailGUID IN (......)
) PVT