SQL - 以列值作为列名的聚合

Posted

技术标签:

【中文标题】SQL - 以列值作为列名的聚合【英文标题】:SQL - aggregation with column value as column name 【发布时间】:2016-09-14 14:16:27 【问题描述】:

对于像下面这样的表需要进行聚合,以便对于一列中的每个唯一字段,需要找到另一列中离散值的出现次数

输入表是:

id  model  datetime     driver   distance
---|-----|------------|--------|---------
1  | S   | 04/03/2009 | john   | 399 
2  | X   | 04/03/2009 | juliet | 244
3  | 3   | 04/03/2009 | borat  | 555
4  | 3   | 03/03/2009 | john   | 300
5  | X   | 03/03/2009 | juliet | 200
6  | X   | 03/03/2009 | borat  | 500
7  | S   | 24/12/2008 | borat  | 600
8  | X   | 01/01/2009 | borat  | 700

需要输出

model  john    juliet | borat
-----|--------|-------|------
 S   | 1      | 0     |  1
 X   | 0      | 2     |  2
 3   | 1      | 0     |  1

一种可能的方法是按model 进行分组,聚合如下 SUM (CASE WHEN driver = 'value' THEN 1 ELSE 0 END) AS value 用于 driver 列的每个离散值。但挑战有时是离散值的数量太多(在我的情况下约为 50),或者在某些情况下甚至不知道所有可能的离散值 - 我想知道是否有其他方法可以做到这一点。

【问题讨论】:

Dynamic pivot query using PostgreSQL 9.3的可能重复 首先进行聚合,然后进行枢轴 【参考方案1】:

聚合部分需要做更多的工作。

这里有详细信息:

需要先计算所有的组合是什么 然后使用LEFT JOIN得到哪个组合没有数据。

DEMO

WITH "allDrivers" as (
    SELECT DISTINCT "driver"
    FROM Table1
), 
"allModels" as (
    SELECT DISTINCT "model"
    FROM Table1
), 
"source" as (
    SELECT d."driver", m."model"
    FROM "allDrivers" d
    CROSS JOIN "allModels" m
)  
SELECT s."model", s."driver", COUNT(t."datetime")
FROM "source" s 
LEFT JOIN table1 t
       ON s."model"  = t."model"
      AND s."driver" = t."driver"
GROUP BY s."model", s."driver"  

输出

| model | driver | count |
|-------|--------|-------|
|     3 |  borat |     1 |
|     3 |   john |     1 |
|     3 | juliet |     0 |
|     S |  borat |     1 |
|     S |   john |     1 |
|     S | juliet |     0 |
|     X |  borat |     2 |
|     X |   john |     0 |
|     X | juliet |     2 |

然后你可以做 dynamic pivot

【讨论】:

你能试试我的答案吗?

以上是关于SQL - 以列值作为列名的聚合的主要内容,如果未能解决你的问题,请参考以下文章

SQL Server:以列值为条件的不同聚合函数[重复]

BigQuery/SQL:如何使用列值作为列名? [复制]

聚合函数

SqlServer基本操作

根据列值返回 SQL Server 列名和对应值

SQL:语句小记