在MSSQL服务器上,给出以下表:
TABLE values { int id; timestamp date; int value; } TABLE value_type { int value_id; // foreign key on values.id text name; }
我可以发出类似的查询:
SELECT date, name, value FROM values LEFT JOIN value_type ON value_id = id;
并得到类似:
+----------+------+-------+ | date | name | value | +----------+------+-------+ | 01.01.10 | foo | 1.0 | +----------+------+-------+ | 01.01.10 | bar | 2.0 | +----------+------+-------+ | 02.01.10 | bar | 4.0 | +----------+------+-------+ | 03.01.10 | foo | 5.0 | +----------+------+-------+
如果我想要这样的数据,查询数据库的最有效方法是什么?
+----------+------+-------+ | date | foo | bar | +----------+------+-------+ | 01.01.10 | 1.0 | 2.0 | +----------+------+-------+ | 02.01.10 | NULL | 4.0 | +----------+------+-------+ | 03.01.10 | 5.0 | NULL | +----------+------+-------+
数据库结构要复杂得多,不幸的是我无法更改它。
编辑 :解决方案不应在查询中使用foo和bar作为硬编码值。
foo
bar
对于SQL Server 2005+,可以使用动态SQL和PIVOT。
PIVOT
DECLARE @ValuesNames NVARCHAR(4000), @Query NVARCHAR(MAX) SET @ValuesNames = '' SELECT @ValuesNames = @ValuesNames + QUOTENAME([name]) + ',' FROM [values] A INNER JOIN value_type B ON B.value_id = A.id GROUP BY [name] ORDER BY [name] SET @ValuesNames = LEFT(@ValuesNames,LEN(@ValuesNames)-1) SET @Query = ' SELECT [date], '+@ValuesNames+' FROM ( SELECT [date], [name], value FROM [values] LEFT JOIN value_type ON value_id = id) A PIVOT(SUM(value) FOR [name] IN ('+@ValuesNames+')) AS PT ' EXEC sp_executesql @Query