2016-06-25 7 views
1

мне нужно собрать результаты этих двух запросов в один возвращение со следующей структурой:Объединение двух запросов с среднемесячным

"date", avg(selic."Taxa"), avg(titulos."puVenda") 

Частичная структура таблиц: таблицы

selic 
"dtFechamento" date, 
"pTaxa" real 

titulos 
"dtTitulo" date, 
"puVenda" real, 
"nomeTitulo" character(30) 

Запроса selic:

select to_char("dtFechamento", 'YYYY-MM') as data, avg("pTaxa") 
from "selic" 
group by data 
order by data 

таблица запросов titulos:

select to_char("dtTitulo", 'YYYY-MM') as data, avg("puVenda") 
from "titulos" 
where "nomeTitulo" = 'LFT010321' 
group by data 
order by data 

Я пробовал подзапрос, но он возвращал поля рядом друг с другом и не мог собрать.

select * 
from (select to_char("dtFechamento", 'YYYY-MM') as data, avg("pTaxa") 
from "selic" 
group by data 
order by data) as selic, 
(select to_char("dtTitulo", 'YYYY-MM') as data, avg("puVenda") 
from "titulos" 
where "nomeTitulo" = 'LFT010321' 
group by data 
order by data) as LFT010321; 
+0

Что нужно вернуть, если только один из запросов имеет результат в течение месяца? NULL для другого? Что за месяцы между ними без результатов в запросе? Нет строки (пропустить месяц)? Или вернуть месяц с двумя значениями NULL? –

+1

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

ответ

1

Предполагая, что вы хотите вернуть одну строку в месяц, когда любой из двух ваших запросов возвращает строку. И пропустите пропущенные значения из другого запроса с помощью NULL.

Используйте FULL [OUTER] JOIN:

SELECT to_char(mon, 'YYYY-MM') AS data, s.avg_taxa, t.avg_venda 
FROM (
    SELECT date_trunc('month', "dtFechamento") AS mon, avg("pTaxa") AS avg_taxa 
    FROM selic 
    GROUP BY 1 
    ) s 
FULL JOIN (
    SELECT date_trunc('month', "dtTitulo")  AS mon, avg("puVenda") AS avg_venda 
    FROM titulos 
    WHERE "nomeTitulo" = 'LFT010321' 
    GROUP BY 1 
    ) t USING (mon) 
ORDER BY mon; 

Это значительно быстрее присоединиться к после агрегирования, чем раньше (меньше операций соединения).

Это также быстрее GROUP BY, JOIN и ORDER на timestamp значений, чем на text исполнение. Обычно также более чистые и менее подверженные ошибкам (хотя в этом конкретном случае текст недвусмыслен). Вот почему я использую date_trunc() вместо to_char() на более низких уровнях.

Если формат месяца не важен, вы можете просто вернуть значение метки времени. Кроме того, вы можете форматировать любой способ, который вам нравится после завершения обработки.

Аналогичный случай с более подробным объяснением:

1

Это должно получить то, что вам нужно. Внутренний «PQ» (PreQuery) объединяет все между каждой возможной датой, но также добавляет столбец флага, чтобы определить, с каким средним он был связан. Каждая часть группируется по дате. Итак, теперь внешний запрос AT MOST содержит 2 записи на определенную дату ... один для налога, другой - Venda. Итак, теперь вам не нужно никакого полного внешнего соединения и не нужно создавать некоторые данные динамического календаря, чтобы получить детали для всех возможных дат.

Таким образом, это возможно только для среднего налога или среднего Venda ИЛИ ОБА.

SELECT 
     PQ.Data, 
     SUM(CASE when PQ.SumType = 'T' then PQ.TypeAvg else 0 end) as AvgTax, 
     SUM(CASE when PQ.SumType = 'V' then PQ.TypeAvg else 0 end) as AvgVenda 
    from 
     (select 
       to_char(dtFechamento, 'YYYY-MM') as data, 
       'T' as sumtype, 
       avg(pTaxa) as TypeAvg 
      from 
       selic 
      group by 
       to_char(dtFechamento, 'YYYY-MM') as data 
     UNION ALL 
     select 
       to_char(dtTitulo, 'YYYY-MM') as data, 
       'V' as sumType, 
       avg(puVenda) as TypeAvg 
      from 
       titulos 
      where 
       nomeTitulo = 'LFT010321' 
      group by 
       to_char(dtTitulo, 'YYYY-MM')) PQ 
    group by 
     PQ.Data 
    order by 
     PQ.Data