如何使用重复的WHERE子句和LEFT JOINS进行查询更加动态(没有crostab)

时间:2014-06-20 20:24:42

标签: sql postgresql

编辑:我使用的是不支持crostab的旧版Postgresql。

我有一个查询,我试图通过更容易添加新值来表示为单个用户汇总信息

每次我在下面添加一个名为算法的列时,我基本上都要编写一个新的左连接和where子句:

┌───────────────────────────────┐
│          algo                 │
├───────────────────────────────┤
│ Algorithm1                    │
│ Algorithm2                    │
│ Algorithm3                    │
└───────────────────────────────┘

这是我写给genarte输出的查询:

select a.userid, a.algo, a.algo1_cnt, b.algo, b.algo2t_cnt, c.algo, c.algo3_cnt
    from
    (select userid, algo, count(*) as algo1_cnt
    from test_table
    where (algo = 'Algorithm1')
    group by 1,2 ) as a
    LEFT OUTER JOIN
    ( select userid, algo, count(*) as algo2_cnt
    from test_table
    where (algo = 'Algorithm2')
    group by 1,2 ) as b
    ON
    (a.userid = b.userid)
    LEFT OUTER JOIN
    ( select userid, algo, count(*) as algo3_cnt
    from test_table
    where (algo = 'Algorithm3')
    group by 1,2 ) as c
    ON
    (a.userid = c.userid)

查询的输出现在看起来像:

┌──────────────────────┬────────────────┬───────────┬───────┬───────────┬───────────────────────────────┬───────────┐
│        userid        │     algo1      │ algo1_cnt │ algo2 │ algo2_cnt │             algo3             │ algo3_cnt │
├──────────────────────┼────────────────┼───────────┼───────┼───────────┼───────────────────────────────┼───────────┤
│ user1                │ algo1          │         3 │       │           │ algo3                         │         2 │
│ user2                │ algo1          │         2 │       │           │                               │           │
  

问题:修改查询以便能够以动态方式从algo列读取不同值并生成相同的outpuy的最佳方法是什么?

我的意思是,如果我向算法列添加一个名为Algorithm4的新值,我可以通过PL / PGSQL或其他一些动态重复来生成相同的输出,而不必使用WHERE(算法4'算法4' )?

1 个答案:

答案 0 :(得分:1)

您可以使用crosstab,但如果您可以在其他地方拆分数组,那么这会更简单

select 
    user_id, 
    array_agg(algo) as algo, 
    array_agg(algo_count) as algo_count
from (
    select userid, algo, count(*) as algo_count
    from test_table
    group by 1, 2
) s
group by 1

JSON爱好者也可以拥有它

select
    user_id,
    format(
        '{%s}',
        string_agg(format('"%s": %s', algo, algo_count), ', ')
    )::json as algo_obj
from (
    select userid, algo, count(*) as algo_count
    from test_table
    group by 1, 2
) s
group by 1