用于3个查询的SQL Query解决方案

时间:2013-09-16 06:50:40

标签: sql postgresql

我有3个查询结果

  z_id  |    data    | c_email_i
--------+------------+-----------
 276050 | 2012-03-30 |         1
 319536 | 2012-07-23 |         1
 190033 | 2010-01-18 |         1
 271987 | 2011-11-02 |         1
 319554 | 2012-08-21 |         1
 370881 | 2013-06-18 |         1

  z_id  |    data    | c_call_o
--------+------------+----------
 169456 | 2009-09-07 |        1
 148231 | 2009-09-25 |        2
 240949 | 2010-10-25 |        2
 119116 | 2009-01-09 |        2
 219206 | 2010-09-29 |        1
 243121 | 2010-11-02 |        1

  z_id  |    data    | c_call_i
--------+------------+----------
 169456 | 2009-09-07 |        1
 148231 | 2009-09-25 |        2
 240949 | 2010-10-25 |        2
 119116 | 2009-01-09 |        2
 219206 | 2010-09-29 |        1
 243121 | 2010-11-02 |        1

我想加入它,就像这样

 z_id |       data       | c_email_i | c_call_o | c_call_i
------+------------------+-----------+----------+----------
119116|     2009-01-09   |         0 |        2 |        2
169456|     2009-09-07   |         0 |        1 |        1
276050|     2012-03-30   |         1 |        0 |        0
...........

我尝试使用UNION,但是有很多列(0作为fake_column)并且我不喜欢它。 (但它真的很快)

另一方面,当我使用左连接时(在日期和z_id表上),查询需要40分钟,结果为800k。

2 个答案:

答案 0 :(得分:1)

有两种方法:

UNION所有三个查询并执行GROUP BY:

select z_id, data, max(c_email_i), nax(c_call_o), max(c_call_i)
from
 (
   select z_id, data, c_email_i, null as c_call_o, null as c_call_i from...
   union all
   select z_id, data, null, c_call_o, null as c_call_i from...
   union all
   select z_id, data, null, null, c_call_i from...
 ) dt
group by z_id, data

或者将查询放在Derived Tables中并加入它们,但是如果它们没有返回相同的z_id / data行,那么很多COALESCE就会变得丑陋:

select
   coalesce(a.z_id, b.z_id, c.z_id),
   coalesce(a.data, b.data, c.data),
   coalesce(a.c_email_i, 0),
   coalesce(b.c_call_o, 0),
   coalesce(c.c_call_i, 0) 
from...
  (select ...) a
full outer join 
  (select ...) b
on a.z_id = b.z_id and a.data = b.data 
full outer join 
  (select ...) c
on coalesce(a.z_id,b.z_id) = c.z_id 
and coalesce(a.data,b.data) = c.data 

答案 1 :(得分:0)

如果您不喜欢使用null as ...,可以使用此查询:

with cte as (
    select 'c_email_i' as type, z_id, data, c_email_i as value from ...
    union all
    select 'c_call_o' as type, z_id, data, c_call_o as value from ...
    union all
    select 'c_call_i' as type, z_id, data, c_call_i as value from ...
)
select
    z_id, data,
    max(case when type = 'c_email_i' then value end) as c_email_i,
    max(case when type = 'c_call_o' then value end) as c_call_o,
    max(case when type = 'c_call_i' then value end) as c_call_i
from cte
group by z_id, data

或子查询:

select
    z_id, data,
    max(case when type = 'c_email_i' then value end) as c_email_i,
    max(case when type = 'c_call_o' then value end) as c_call_o,
    max(case when type = 'c_call_i' then value end) as c_call_i
from (
    select 'c_email_i' as type, z_id, data, c_email_i as value from ...
    union all
    select 'c_call_o' as type, z_id, data, c_call_o as value from ...
    union all
    select 'c_call_i' as type, z_id, data, c_call_i as value from ...
) as c
group by z_id, data