PLSQL: где условие вне подзапроса - PullRequest
0 голосов
/ 23 ноября 2018

У меня такой запрос (оригинал намного сложнее)

select 0, 999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
   count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 0 and 999
union
select 1000, 2999, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
   count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
from myTable
where amount between 1000 and 2999
union
...

Существует несколько объединений, и выбор намного сложнее.

Я бы хотел упростить это.Для этого я использовал предложение with

with q1 as(
    select case when cond = 'aa' then 1 end val1, case when cond = 'aa' then amount else 0 end amount1,
           case when cond = 'bb' then 1 end val2, case when cond = 'bb' then amount else 0 end amount2
)
select 0, 999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 0 and 999
union
select 1000, 2999, sum(val1) val1, sum(amount1) amount1, sum(val2) val2, sum(amount2) amount2
from q1 where amount between 1000 and 2999
union
....

Но в моем случае это все еще очень долго.Есть ли возможность в plsql написать это так:

with q1 as (
   select minVal, maxVal, count(case when cond = 'aa' then 1 end) val1, sum(case when cond = 'aa' then amount else 0 end) amount1,
      count(case when cond = 'bb' then 1 end) val2, sum(case when cond = 'bb' then amount else 0 end) amount2
   from myTable
   where amount between minVal and maxVal
)
      select * from q1 insideWhere minVal=0 and maxVal=999
union select * from q1 insideWhere minVal=1000 and maxVal=2999
union ...

или любое другое решение?

Ответы [ 2 ]

0 голосов
/ 23 ноября 2018

Чтобы сделать то, что вы пытаетесь, вам нужно объединить группы min / max в табличную структуру.Вы уже прошли большую часть пути: самый простой способ сделать это - использовать предложение WITH.

WITH value_groups AS
         (SELECT 0 AS min_val, 999 AS max_val FROM DUAL
          UNION ALL
          SELECT 1000, 2999 FROM DUAL),
     q1 AS
         (SELECT *
          FROM   my_table
                 PIVOT
                     (COUNT (*) FOR cond IN ('aa' AS aa, 'bb' AS bb)))
SELECT   min_val,
         max_val,
         COUNT (aa) as val1,
         SUM (aa * amount) as amount1,
         COUNT (bb) as val2,
         SUM (bb * amount) as amount2 
FROM     q1 JOIN value_groups ON amount BETWEEN min_val AND max_val
GROUP BY min_val, max_val

Я также преобразовал ваши операторы CASE в сводную таблицу.Это сгруппирует совпадающие наборы количества / количества (то есть, если есть две строки 'aa' с количеством 100, которые будут возвращены как сумма = 100, количество = 2), поэтому я умножаю эти два, чтобы получитьправильная сумма.

0 голосов
/ 23 ноября 2018

Похоже, это должен быть один агрегированный запрос, например:

SELECT min_val,
       max_val,
       COUNT(CASE WHEN cond = 'aa' THEN 1 END) val1,
       SUM(CASE WHEN cond = 'aa' THEN amount ELSE 0 END) amount1,
       COUNT(CASE WHEN cond = 'bb' THEN 1 END) val2,
       SUM(CASE WHEN cond = 'bb' THEN amount ELSE 0 END) amount2,
FROM   (SELECT cond,
               amount,
               CASE WHEN amount BETWEEN 0 AND 999 THEN 0
                    WHEN amount BETWEEN 1000 AND 2999 THEN 1000
               END min_val,
               CASE WHEN amount BETWEEN 0 AND 999 THEN 999
                    WHEN amount BETWEEN 1000 AND 2999 THEN 2999
               END max_val
        FROM   mytable) -- using a subquery here to avoid repeating the case statement in both the select column list and the group by column list
GROUP BY min_val,
         max_val;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...