我有一个基于键值的属性表。例如:
CREATE TABLE ObjectAttributes
(
int objectId, key nvarchar(64), value nvarchar(512)
)
当我从中选择时,我得到:
objectId key value
----------------------------
1 Key 1 Value 1
1 Key 2 Value 2
我想知道我是否可以使用PIVOT语法将其转换为:
objectId Key 1 Key 2
---------------------------
1 Value 1 Value 2
我知道我的所有表都有相同的键。 (不幸的是我无法轻易改变表结构。这就是导致我尝试使用PIVOTS的原因。)
这里的一个重要问题是枢轴需要使用聚合函数。有办法避免这种情况吗?尝试这个我完全错了吗?或者有更好的解决方案吗?
答案 0 :(得分:10)
对于固定的列输出,枢轴将不会更快,然后重复自连接。
SELECT
T1.objectID, T1.Value AS Key1, T2.Value AS Key2
FROM
ObjectAttributes T1
JOIN
ObjectAttributes T2 ON T1.objectID = T2.objectID
WHERE
T1.key = 'Key 1'
AND
T2.key = 'Key 2'
如果你想使用PIVOT,那么只需使用MAX。因为每个对象/键有一行,所以无论如何它都是微不足道的,并且满足PIVOT要求。
如果要将未知行数存储到列中,则它是动态SQL(根据SQL Server 2000解决方案)或在客户端代码中执行。
如果每个对象具有固定数量的属性,那么我会考虑使用由触发器维护的实数列的第二个表。笨拙,但让生活更容易阅读
答案 1 :(得分:6)
不,你无法避免聚合。 SQL Server需要某种方法将许多可能的行组合成一个值。您碰巧有一个值,但 PIVOT 功能是在考虑许多行的情况下制作的。
SELECT objectId, [Key 1], [Key 2]
FROM
(SELECT objectId, [key], value FROM ObjectAttributes) AS source
PIVOT
(
MIN(value)
FOR [key] IN ([Key 1], [Key 2])
) as pvt
答案 2 :(得分:0)
我要添加此答案,因为此线程是Google上针对该问题出现的第一个线程。
我发现的最简单的解决方案是使用max与case的组合,如下所示:
-- Pivot the data with a handwritten T-SQL statement.
-- Make sure you have an index defined on the grouping column.
SELECT
RecordID,
-- Spreading and aggregation phase
MAX(CASE WHEN Element = 'FirstName' THEN Value END) AS 'FirstName',
MAX(CASE WHEN Element = 'LastName' THEN Value END) AS 'LastName',
MAX(CASE WHEN Element = 'City' THEN Value END) AS 'City',
MAX(CASE WHEN Element = 'Country' THEN Value END) AS 'Country'
FROM EAVTable
GROUP BY RecordID -- Grouping phase
该解决方案几乎也适用于所有人,如果需要旋转许多列,则不需要太多的连接
答案 3 :(得分:0)
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(your_key_column)
from YOUR_ORIGINAL_KEY_AND_VALUE_TABLE
group by your_key_column
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query = 'SELECT your_row_heading_columns,' + @cols + '
INTO YOUR_NEW_PIVOTED_TABLE
from
(
select your_row_heading_columns,your_key_column,your_value_column
from YOUR_ORIGINAL_KEY_AND_VALUE_TABLE
) x
pivot
(
max(your_value_column)
for your_key_column in (' + @cols + ')
) p '
execute sp_executesql @query;