将“flat”SQL查询结果转换为表结构

时间:2009-10-12 15:13:05

标签: sql pivot

我有一个返回结果的Sql表,如下所示:

Amount  Descrip
----------------------------
1.34    Group1  Description1
2.36    Group2  Description2
5.46    Group3  Description3
4.54    Group1  Description4
6.23    Group2  Description5

我需要让它看起来像这样。

Descrip      Group1 Group2  Group3 
------------------------------------
Description1 1.34
Description2        2.36 
Description3                5.46
Description4 4.54
Description5        6.23

要记住的是,没有关于第3组将存在的规则或任何组的规则。组列表由查询结果确定。我可以一次拥有Group1,Group2,Group4和Group6,但没有group4但又有group5。

我知道我可以在.Net代码中执行此操作,但在代码中会耗费大量时间。我宁愿在SQL服务器中执行它只是绑定到结果集。

作为旁注,如果有一种方法可以汇总值以获得总计(如Group1的5.88),那将是很好的。我可以在runt time进行计算,但是如果可以的话,我也想做服务器端。

3 个答案:

答案 0 :(得分:0)

查看使用pivot

SELECT 'Amount' AS MaxAmount, [Group1], [Group2], [Group3]
  FROM
(SELECT descrip, Amount 
    FROM Table) AS SourceTable
PIVOT
(
Max(Amount)
FOR descrip IN ([Group1], [Group2], [Group3])
) AS PivotTable;

需要输入适当的聚合函数,对于此示例,我使用了max。

答案 1 :(得分:0)

就像SeriousCallersOnly所说,你需要一个支点声明。不幸的是,要使用那些你必须在实际值(“Group1”,“Group2”,“Group3”等)中进行硬编码的那些。如果在运行时之前无法确定它们,则必须在运行时构建查询,这意味着构建和执行动态代码。这并不简单。如果你确实需要做很多这样的查询,你必须[必须]相当擅长它;如果这是你认为你曾经做过的唯一一个地方,你可能最好不要在应用程序方面担负这项工作。

(另一种可能性:所有可能的透视值中的硬编码,然后让应用程序忽略“空”列。如果透视值是随机的,任意的或用户输入的话,这不起作用。)

答案 2 :(得分:0)

如果要将行数据更改为列(AKA数据透视表),最广泛支持的方法是使用CASE语句:

SELECT t.descrip,
       CASE WHEN t.descrip LIKE 'GROUP 1%' THEN t.amount END 'Group 1',
       CASE WHEN t.descrip LIKE 'GROUP 2%' THEN t.amount END 'Group 2',
       CASE WHEN t.descrip LIKE 'GROUP 3%' THEN t.amount END 'Group 3',
       ...etc

这也意味着如果您没有特定描述的记录,该值将显示为NULL。 SQL是全有或全无的事情 - 列将存在或不在整个结果集中。

根据您的数据库,有一些语法可以提供帮助。例如,SQL Server自SQL Server 2005以来就支持PIVOT功能.Oracle将其添加到11g中。我不相信MySQL或Postgres有枢轴功能 - 你必须使用CASE语句。

对于拥有动态组,您需要使用动态SQL来适应。 CASE和PIVOT功能都无法处理 - 必须为查询定义输出列。