2013-09-16 3 views
1

У меня есть эти 3 запросов приводятрешения SQL запросов для 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

Какие СУБД вы используете? Postgres? Oracle? И, пожалуйста, покажите запрошенные вами запросы. –

+0

Postgres, забыл упомянуть об этом, спасибо. – tomaspavlic

ответ

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 

Или поставить вопросы в производных таблицах и присоединиться к ним, но если они не возвращая же z_id/строк данных он становится уродливым с большим количеством 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 
+0

У меня есть более 3 запросов, так что бы вы предпочли использовать, потому что в первом решении будет «select ss.z_id, ss.s_send_intime :: date Date, count (ss.s_id) как C_SMS_O, 0 as C_SMS_I, 0 как C_EMAIL_O, 0 как C_EMAIL_O_M, 0 как C_CALLS_O, 0 как C_CALLS_I, 0 как COLLECTION, 0 как C_SEARCHING, 0 как C_EMAIL_I, 0 как C_MAIL_O, 0 как C_MAIL_I ", и я думаю, что слишком много 0 в качестве столбца – tomaspavlic

+0

Я бы все еще выполняйте UNION ALL, потому что, используя ПОЛНЫЕ ПРИСОЕДИНИЕ, вы должны делать слишком много COALESCE :-) Но по всем этим запросам: вы получаете доступ к одной и той же таблице или к другим? Если это то же самое, вы можете использовать один запрос с некоторыми CASE. – dnoeth

+0

Нет, это уже sql-запрос из разных мест. Но спасибо вам большое. Я просто хотел быть уверенным, что профсоюзные решения - неплохая идея:] – tomaspavlic

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 
+0

Привет, спасибо за совет, он отлично работает, но я обнаружил, что 50% баз данных, где мне нужно использовать эту версию ниже 8.4. – tomaspavlic

+0

, так что вы можете использовать подзапрос для этого см. Обновленный –

Смежные вопросы