如何在SQL中创建名称-值对表
使用SQL,如何转换这样的单行表如何在SQL中创建名称-值对表,sql,Sql,使用SQL,如何转换这样的单行表 Firstname Surname Address1 City Country --------- ------- --------------- ------ ------- Bob Smith 101 High Street London UK …到一个包含名称-值对的表,如下所示: Name Value --------- ------- Firstname Bob Surname Smith Ad
Firstname Surname Address1 City Country
--------- ------- --------------- ------ -------
Bob Smith 101 High Street London UK
…到一个包含名称-值对的表,如下所示:
Name Value
--------- -------
Firstname Bob
Surname Smith
Address1 101 High Street
City London
Country UK
此脚本将创建原始表:
create table #OriginalTable (Firstname varchar(10), Surname varchar(10),
Address1 varchar(50), City varchar(10), Country varchar(10))
insert into #OriginalTable
select
'Bob' Firstname,
'Smith' Surname,
'101 High Street' Address1,
'London' City,
'UK' Country
我想要的是一个通用解决方案,它不依赖于列名称始终与示例中的列名称相同
编辑:
我正在使用SQLServer2005。
我想要的解决方案是使用SQL脚本将这些数据转换为名称-值对表
答复:
使用我接受的答案,这就是我使用的:
select
result.Name,
result.Value
from
(select
convert(sql_variant,FirstName) AS FirstName,
convert(sql_variant,Surname) AS Surname,
convert(sql_variant,Address1) AS Address1,
convert(sql_variant,City) AS City,
convert(sql_variant,Country) AS Country
from #OriginalTable) OriginalTable
UNPIVOT (Value For Name In (Firstname, Surname, Address1, City, Country)) as result
这听起来像是自2005年以来PIVOT子句可以做的事情(查看第一个示例),但是您没有提到您使用的是哪种数据库引擎。这不是一个完整的解决方案,而是一个头脑风暴的想法,如果您将信息与表中的schema.columns交叉连接会怎么样
SELECT column_name, OriginalTable.*
FROM information_schema.columns
CROSS JOIN OriginalTable
WHERE table_name = 'OriginalTable'
AND /* PRIMARY KEY FILTER HERE*/
通常,使用应用程序代码在应用程序中进行透视是最有效的。数据透视并不是数据库的强项。使用两个表。一个表作为“键”表,主表包含键表的id和值
然后,您可以向主表中添加
client\u id
之类的内容,并在client\u id
和key\u id
上设置一个唯一的键。基本上,您有两个问题-要UNPIVOT
,数据类型必须一致。另一个问题是列数未知。您希望达到以下形式:
WITH conformed
AS ( SELECT CONVERT(VARCHAR(255), [Firstname]) AS [Firstname],
CONVERT(VARCHAR(255), [Surname]) AS [Surname],
CONVERT(VARCHAR(255), [Address1]) AS [Address1],
CONVERT(VARCHAR(255), [City]) AS [City],
CONVERT(VARCHAR(255), [Country]) AS [Country]
FROM so1526080
)
SELECT ColumnKey,
ColumnValue
FROM conformed UNPIVOT ( ColumnValue FOR ColumnKey IN ( [Firstname], [Surname], [Address1], [City], [Country] ) ) AS unpvt
因此,使用使用元数据的动态SQL PIVOT(您可能需要使用TABLE_SCHEMA等来解决这个问题):
这是使用JSON的MS SQL Server解决方案。您不需要指定列名和数据类型。您只需在第3行指定表名和有效的where条件
DECLARE @TEMP TABLE (JSONHOLDER NVARCHAR(MAX));
INSERT INTO @TEMP
SELECT (SELECT * FROM YOURTABLE WHERE YOURID = 2589 FOR JSON AUTO) AS JSONHOLDER
SELECT [KEY] as ColumnName, [VALUE] as ColumnValue FROM (SELECT [KEY] AS OLDKEY, [VALUE] AS OLDVALUE FROM @TEMP A
CROSS APPLY OPENJSON(A.JSONHOLDER)) B CROSS APPLY OPENJSON(B.OLDVALUE)
您使用的是什么数据库管理系统?不同的数据库管理系统以不同的方式存储列的名称,所以每个键都有多行?e、 g.如果原始表中不仅有Bob Smith的一行,还有John Doe的一行,那么您的名称-值对表中的每个键将有2行。请参阅类似问题的答案:@Dominic。否,原始表将始终只有一行。如果数据库中有更多的行供不同的人使用,那么原始表仍然只有一行,b/c它只是一个人的过滤器。您可以使用UNPIVOT进行操作。我读了这个问题,然后发现这个:。我会尝试一下。我不认为你可以在不知道字段名的情况下进行透视。但是如果可以,请发布SQLServer。对不起,我自己不使用SQL Server,只在Microsoft文档中阅读。
DECLARE @TEMP TABLE (JSONHOLDER NVARCHAR(MAX));
INSERT INTO @TEMP
SELECT (SELECT * FROM YOURTABLE WHERE YOURID = 2589 FOR JSON AUTO) AS JSONHOLDER
SELECT [KEY] as ColumnName, [VALUE] as ColumnValue FROM (SELECT [KEY] AS OLDKEY, [VALUE] AS OLDVALUE FROM @TEMP A
CROSS APPLY OPENJSON(A.JSONHOLDER)) B CROSS APPLY OPENJSON(B.OLDVALUE)