Sql 将元组值转换为列名

Sql 将元组值转换为列名,sql,postgresql,group-by,pivot,crosstab,Sql,Postgresql,Group By,Pivot,Crosstab,得到了类似于: +-------+------+-------+ | count | id | grade | +-------+------+-------+ | 1 | 0 | A | | 2 | 0 | B | | 1 | 1 | F | | 3 | 1 | D | | 5 | 2 | B | | 1 | 2 | C | 我需要: +-----+---+

得到了类似于:

+-------+------+-------+
| count |  id  | grade |
+-------+------+-------+
|     1 |    0 | A     |
|     2 |    0 | B     |
|     1 |    1 | F     |
|     3 |    1 | D     |
|     5 |    2 | B     |
|     1 |    2 | C     |
我需要:

+-----+---+----+---+---+---+
| id  | A | B  | C | D | F |
+-----+---+----+---+---+---+
|   0 | 1 |  2 | 0 | 0 | 0 |
|   1 | 0 |  0 | 0 | 1 | 1 |
|   2 | 0 |  5 | 1 | 0 | 0 |
我不知道我是否能做到这一点。我可以按id分组,但您如何读取每个年级列的计数值?

您需要一个“透视”表或“交叉制表”。您可以使用聚合和
CASE
语句的组合,或者更优雅地使用附加模块
tablefunc
提供的
交叉表()。所有基本信息如下:

由于并非
grade
中的所有键都有值,因此需要双参数表单。像这样:

SELECT * FROM crosstab(
        'SELECT id, grade, count FROM table ORDER BY 1,2'
       , $$SELECT unnest('{A,B,C,D,F}'::text[])$$
       ) ct(id text, "A" int, "B" int, "C" int, "D" int, "F" int);

第一个表是查询的结果吗?如果是这样的话,也要展示你原来的表格结构,因为可能有一个更容易得到最终结果的解决方案。是的!我有一些基本上能给出id,等级,等级的东西。我按ID和等级分组并计算元组。为什么不简单地
值('A')、('B')、('C')、('D')、('F')
,而不是创建一个数组,然后立即分解它呢?@Patrick:因为它的语法比几个项目都要短。我想在文档部分写一篇关于crosstab/pivot/dynamic pivot的文章。不幸的是,我的英语不太好…@Abelisto:也许吧。我还没有对所谓“文档”的整个概念产生兴趣,这应该被称为“规范性示例”。Postgres有一个优秀的官方文档,该文档由项目保持最新。我不认为我们应该在现有的SO特性之外开始一个并行的Postgres文档。但这确实是一个关于meta的讨论,并且已经讨论了很多。有没有不使用交叉表的方法?这是关于PostgreSQL的,不是MS SQL。好的,但没有提到任何地方。这对MS SQL用户有帮助。这是带标签的PostgreSQL。再清楚不过了。这个答案不适用。
CREATE TABLE #MyTable(_count INT,id INT , grade VARCHAR(10))

INSERT INTO #MyTable( _count ,id  , grade )
SELECT 1,0,'A' UNION ALL
SELECT 2,0,'B' UNION ALL
SELECT 1,1,'F' UNION ALL
SELECT 3,1,'D' UNION ALL
SELECT 5,2,'B' UNION ALL
SELECT 1,2,'C' 


SELECT *
FROM
(
 SELECT _count ,id  ,grade
 FROM #MyTable
)A
PIVOT
(
  MAX(_count) FOR grade IN ([A],[B],[C],[D],[F])
)P