Добро пожаловать в форум, Guest  >>   Войти | Регистрация | Поиск | Правила | В избранное | Подписаться
Все форумы / Oracle Новый топик    Ответить
 Как получить следующий результат?  [new]
Автор:
Guest
Допустим имеется табличка
type_id      | S1   | S2
-----------------------------
1            | 1    |  2
1            | 3    |  4
1            | 5    |  6
2            | 7    |  8
2            | 9    |  10

Хотелось бы получить следующий результат
type_id      | ind | Cnt1   | Cnt2
---------------------------------
1            | 10  |  2     |   1
1            | 20  |  1     |   2
2            | 20  |  2     |   2

Где ind = 10, если S1 "или" S2 меньше 4 и 20, если больше или равно.
То есть если рассмотреть первую строку результата: в источнике для type_id = 1 есть две строки с S1 меньше 4 => Cnt1 = 2 и одна строка с S2 меньше 4 => 1

В самой задаче ind более хитрый case, на более чем две группы.

Хотя бы вложенными запросами. Пока придумал только вариант: для каждой S1 и S2 посчитать отдельно, а потом outer join сделать по type_id и ind. Только это плохо :( поскольку источник здоровый (30млн строк).
15 май 07, 16:34    [4140049]     Ответить | Цитировать Сообщить модератору
 Re: Как получить следующий результат?  [new]
SQL*Plus
Member

Откуда: Россия, Москва
Сообщений: 8131
Каков алгоритм вычисления остальных двух строк?
type_id      | ind | Cnt1   | Cnt2
---------------------------------
...
1            | 20  |  1     |   2
2            | 20  |  2     |   2
15 май 07, 17:30    [4140502]     Ответить | Цитировать Сообщить модератору
 Re: Как получить следующий результат?  [new]
Ivan Rishko
Member

Откуда:
Сообщений: 29
Один из вариантов.
Правда надо отфильтровать ненужные (нулевые) строки.

with t1 as
     (select 1 type_id, 1 s1, 2 s2
        from dual
      union all
      select 1 type_id, 3 s1, 4 s2
        from dual
      union all
      select 1 type_id, 5 s1, 6 s2
        from dual
      union all
      select 2 type_id, 7 s1, 8 s2
        from dual
      union all
      select 2 type_id, 9 s1, 10 s2
        from dual),
     t2 as
     (select 10 ind
        from dual
      union all
      select 20
        from dual)
select   t1.type_id, t2.ind, sum (case
                                     when (s1 < 4 and t2.ind=10)
                                        then 1
                                     when (s1 >= 4 and t2.ind=10)
                                        then 0
                                     when (s1 < 4 and t2.ind=20)
                                        then 0
                                     when (s1 >= 4 and t2.ind=20)
                                        then 1 
                                     else 
                                        null
                                  end) cnt1, 
                              sum (case
                                     when (s2 < 4 and t2.ind=10)
                                        then 1
                                     when (s2 >= 4 and t2.ind=10)
                                        then 0
                                     when (s2 < 4 and t2.ind=20)
                                        then 0
                                     when (s2 >= 4 and t2.ind=20)
                                        then 1
                                     else 
                                        null
                                  end) cnt2 
    from t1, t2
group by t1.type_id, t2.ind
15 май 07, 17:36    [4140541]     Ответить | Цитировать Сообщить модератору
 Re: Как получить следующий результат?  [new]
Автор:
Guest
Вторая результирующая строка
Для type_id = 1 с больше или равно 4, т.е .ind = 2
S1 имеется одна строка (S1 = 5) => 1
S2 имеется две строки (S2 = 4 и 6) => 2


Третья результирующая строка
Для type_id = 2
Имеется две строки с S1 >= 4 (7 и 9) и две строки с S2 >= 4 (8 и 10), то есть все Ind = 2
15 май 07, 17:38    [4140560]     Ответить | Цитировать Сообщить модератору
 Re: Как получить следующий результат?  [new]
Автор:
Guest
В последнем сообщении ind = 10 и 20 надо.

2Ivan Rishko
Надо было поточнее сформулировать
S1, S2 и т.д будет 11 штук и "справочник" ind не две штуки, а более 20 =(
Хотя может и пойдет, спасибо :D (надо повтыкать еще, а то я уж аналитикой пытаюсь сделать)
15 май 07, 17:48    [4140633]     Ответить | Цитировать Сообщить модератору
 Re: Как получить следующий результат?  [new]
Ivan Rishko
Member

Откуда:
Сообщений: 29
Автор:

S1, S2 и т.д будет 11 штук и "справочник" ind не две штуки, а более 20 =(


Тогда посмотри такой вариант, правда я не в курсе дизайна вашей базы.

with t1 as
     (select 1 type_id, 1 s1, 2 s2
        from dual
      union all
      select 1 type_id, 3 s1, 4 s2
        from dual
      union all
      select 1 type_id, 5 s1, 6 s2
        from dual
      union all
      select 2 type_id, 7 s1, 8 s2
        from dual
      union all
      select 2 type_id, 9 s1, 10 s2
        from dual),
     t2 as
     (select 10 ind, 0 aa, 4 bb
        from dual
      union all
      select 20, 4 aa, 99 bb
        from dual)
select   t1.type_id, t2.ind, sum (case
                                     when (s1 >= t2.aa and s1 < t2.bb)
                                        then 1
                                     else 
                                        0
                                  end) cnt1,
                             sum (case
                                     when (s2 >= t2.aa and s2 < t2.bb)
                                        then 1
                                     else 
                                        0
                                  end) cnt2
    from t1, t2
group by t1.type_id, t2.ind
15 май 07, 18:00    [4140726]     Ответить | Цитировать Сообщить модератору
 Re: Как получить следующий результат?  [new]
Автор:
Guest
Ура, вопрос по все видимости закрыт =D


       sum(case
             when (S1 < 4 and T2.IND = 10) then
              1
             when (S1 >= 4 and T2.IND = 10) then
              0
             when (S1 < 4 and T2.IND = 20) then
              0
             when (S1 >= 4 and T2.IND = 20) then
              1
             else
              null
           end) CNT1

Заменил на
       sum(case
             when (case_получение_IND_по_значению (S1) = T2.IND) then
              1
             else
              0
           end) CNT1

Ivan Rishko, еще раз спасибо =)
P.S. Теперь осталось проверить это на производительность - декартово произведение все таки.
15 май 07, 18:05    [4140769]     Ответить | Цитировать Сообщить модератору
Все форумы / Oracle Ответить