Как естественным образом объединить два запроса, имеющих предложение with?

#postgresql

#postgresql

Вопрос:

Я написал два запроса, которые помогают в нахождении минимального и максимального количества продаж для разных продуктов. Теперь мне нужно объединить эти два запроса, используя естественное объединение, для вывода одной таблицы.

Запрос 1:

 with max_quant_table as
(with maxquant_table as
(select distinct month,prod as prod, sum(quant) as quant from sales group by month,prod)
 select month as month,prod as MOST_POPULAR_PROD, quant as  MOST_POP_TOTAL_Q
from maxquant_table)
select t2.* from
    (select month, max(MOST_POP_TOTAL_Q) maxQ FROM max_quant_table group by month order by month asc)
    t1 join max_quant_table t2 on t1.month = t2.month and (t2.MOST_POP_TOTAL_Q =maxQ)
  

Запрос 2:

 with min_quant_table as
(with minquant_table as
(select distinct month,prod as prod, sum(quant) as quant from sales group by month,prod)
 select month as month,prod as LEAST_POPULAR_PROD, quant as  LEAST_POP_TOTAL_Q
from minquant_table)
select t2.* from
    (select month, min(LEAST_POP_TOTAL_Q) minQ FROM min_quant_table group by month order by month asc)
    t1 join min_quant_table t2 on t1.month = t2.month and (t2.LEAST_POP_TOTAL_Q = minQ)
  

Комментарии:

1. Не связано, но: если вы используете group by month, prod , нет необходимости также добавлять distinct к вашему запросу.

Ответ №1:

Вы слишком все усложняете. Вам не нужно объединять эти два запроса (и вам действительно следует держаться подальше от естественного соединения), вам нужно только объединить их. min() и max() могут использоваться внутри одного запроса, нет необходимости запускать два запроса для оценки обоих.

Вам также не нужно вкладывать определения CTE, вы можете просто писать одно за другим.

Итак, что-то вроде этого:

 with quant_table as (
  select month, prod, sum(quant) as sum_q
  from sales 
  group by month, prod
), min_max as (
  select month, max(sum_q) as max_q, min(sum_q) as min_q
  from quant_table 
  group by month 
)
select t1.* 
from quant_table t1
  join min_max t2 
    on t2.month = t1.month 
   and t1.sum_q in (t2.min_q, t2.max_q)
order by month, prod;
  

Условие and t1.sum_q in (t2.min_q, t2.max_q) также может быть записано как and (t2.max_q = t1.sum_q or t2.min_q = t1.sum_q) .


Вышесказанное можно дополнительно упростить, объединив group by с оконными функциями и выполнив вычисление суммы, min и max в одном запросе:

 with min_max as (
  select month, prod, 
         sum(quant) as sum_q,
         max(sum(quant)) over (partition by month) as max_q,
         min(sum(quant)) over (partition by month) as min_q
  from sales 
  group by month, prod
)
select month, prod, sum_q
from min_max
where sum_q in (max_q, min_q)
order by month, prod;
  

Комментарии:

1. Спасибо, что поделились этим. Я знаю, что мы можем объединить min() и max() в одном запросе, но я хочу, чтобы для минимальных и максимальных значений отображались отдельные таблицы.

2. @webMonk: если вам нужны «отдельные таблицы», вы также не можете использовать объединение, поскольку это также приводит к единому результату (= таблица)