Что касается группы по - Oracle 10g

Использование Oracle10g. Я использую «случай, когда» в предложении GROUP BY. Проблема в том, что я использую:

a.book_name IN (SELECT BOOK 
                  FROM BOOK_CONF)

Он говорит, что это не предложение GROUP BY. Может ли кто-нибудь помочь мне в этом?

  SELECT pub_name, 
         CASE 
           WHEN a.book_name IN (SELECT BOOK FROM BOOK_CONF) THEN 'UNI'   
           WHEN a.book_name ='JAVA' THEN 'JAVA'    
           ELSE 'MIS'    
         END) test, 
         COUNT(*) 
    FROM books a 
GROUP BY pub_name, 
         CASE 
           WHEN a.book_name in (SELECT BOOK FROM BOOK_CONF) THEN 'UNI'
           WHEN a.book_name ='JAVA' THEN 'JAVA'    
         ELSE 'MIS'

person Arav    schedule 14.04.2011    source источник


Ответы (4)


Самый ранний Oracle позволяет ссылаться на псевдонимы столбцов ORDER BY - в противном случае вы получите ORA-00904: Invalid Identifier (IME, то есть до 10g включительно - не знаю, изменилось ли это в 11g). Таким образом, самый простой способ приспособиться к этому - использовать производное табличное/встроенное представление:

  SELECT x.pub_name,
         x.test,
         COUNT(*)
    FROM (SELECT a.pub_name, 
                 CASE 
                   WHEN a.book_name IN (SELECT BOOK FROM BOOK_CONF) THEN 'UNI'   
                   WHEN a.book_name ='JAVA' THEN 'JAVA'    
                   ELSE 'MIS'    
                 END AS test
            FROM BOOKS a) x
GROUP BY x.pub_name, x.test
person OMG Ponies    schedule 14.04.2011
comment
Большое спасибо за информацию. Попробовал запустить второй. Это дает мне ORA-00979: не выражение GROUP BY и выделение a.book_name. - person Arav; 14.04.2011
comment
@Arav: У меня это сработало на 10g-XE, поэтому я сначала предлагаю производное табличное/встроенное представление. - person OMG Ponies; 14.04.2011
comment
К вашему сведению: 11g также не позволяет использовать псевдонимы в группе by. - person MacAnthony; 14.04.2011

Пожалуйста, позвольте мне подвести итог, потому что здесь смешаны и хорошие, и плохие советы.

Сначала ваши таблицы с некоторыми примерами данных:

SQL> create table books (book_name,pub_name)
  2  as
  3  select 'JAVA', 'PUB1' from dual union all
  4  select 'JAVA', 'PUB2' from dual union all
  5  select 'ABC', 'PUB1' from dual union all
  6  select 'XYZ', 'PUB3' from dual union all
  7  select 'KLM', 'PUB3' from dual
  8  /

Table created.

SQL> create table book_conf (book)
  2  as
  3  select 'XYZ' from dual union all
  4  select 'KLM' from dual
  5  /

Table created.

Ваш запрос:

SQL> SELECT pub_name
  2       , CASE
  3         WHEN a.book_name IN (SELECT BOOK FROM BOOK_CONF) THEN
  4           'UNI'
  5         WHEN a.book_name ='JAVA' THEN
  6           'JAVA'
  7         ELSE
  8           'MIS'
  9         END test
 10       , COUNT(*)
 11    FROM books a
 12   GROUP BY pub_name
 13       , CASE
 14         WHEN a.book_name in (SELECT BOOK FROM BOOK_CONF) THEN
 15           'UNI'
 16         WHEN a.book_name ='JAVA' THEN
 17           'JAVA'
 18         ELSE
 19           'MIS'
 20         END
 21  /
       WHEN a.book_name IN (SELECT BOOK FROM BOOK_CONF) THEN
            *
ERROR at line 3:
ORA-00979: not a GROUP BY expression

Это НЕ потому, что выражение CASE не разрешено в предложении group by. Это потому, что вы используете оператор SELECT внутри предложения GROUP BY. Если вы замените "IN (SELECT book FROM book_conf)" на "IN ('XYZ','KLM')", вы увидите, что теперь ваше утверждение выполнено успешно:

SQL> SELECT pub_name
  2       , CASE
  3         WHEN a.book_name IN ('XYZ','KLM') THEN
  4           'UNI'
  5         WHEN a.book_name ='JAVA' THEN
  6           'JAVA'
  7         ELSE
  8           'MIS'
  9         END test
 10       , COUNT(*)
 11    FROM books a
 12   GROUP BY pub_name
 13       , CASE
 14         WHEN a.book_name in ('XYZ','KLM') THEN
 15           'UNI'
 16         WHEN a.book_name ='JAVA' THEN
 17           'JAVA'
 18         ELSE
 19           'MIS'
 20         END
 21  /

PUB_ TEST   COUNT(*)
---- ---- ----------
PUB1 MIS           1
PUB1 JAVA          1
PUB2 JAVA          1
PUB3 UNI           2

4 rows selected.

Приведенный ниже запрос выглядит великолепно, не выдает ошибку, но дает другой результат, потому что теперь вы группируете по book_name, а не по CASE-выражению:

SQL> select a.pub_name
  2       , (CASE WHEN a.book_name in (SELECT BOOK FROM BOOK_CONF) THEN 'UNI'
  3               WHEN a.book_name ='JAVA' THEN 'JAVA'
  4               ELSE 'MIS'
  5          END) test
  6       , count(*)
  7    from books a
  8   group by a.pub_name
  9       , a.book_name
 10  /

PUB_ TEST   COUNT(*)
---- ---- ----------
PUB1 MIS           1
PUB1 JAVA          1
PUB2 JAVA          1
PUB3 UNI           1
PUB3 UNI           1

5 rows selected.

OMG Ponies использует правильный подход, инкапсулируя группу по выражению во встроенном представлении:

SQL> select pub_name
  2       , book_type
  3       , count(*)
  4    from ( select pub_name
  5                , case
  6                  when book_name in (select book from book_conf) then
  7                    'UNI'
  8                  when book_name = 'JAVA' then
  9                    'JAVA'
 10                  else
 11                    'MIS'
 12                  end book_type
 13             from books
 14         )
 15   group by pub_name
 16       , book_type
 17  /

PUB_ BOOK   COUNT(*)
---- ---- ----------
PUB1 MIS           1
PUB1 JAVA          1
PUB2 JAVA          1
PUB3 UNI           2

4 rows selected.

Надеюсь это поможет.

С уважением,
Роб.

person Rob van Wijk    schedule 14.04.2011
comment
Большое спасибо за ваше время. Если вы замените IN (SELECT book FROM book_conf) на IN ('XYZ','KLM'), вы увидите, что теперь ваше утверждение выполнено успешно. У меня не может быть IN, потому что у меня может быть 1000 записей. Так что встроенный вид - это решение для меня. - person Arav; 15.04.2011
comment
Мой смысл этого запроса состоял в том, чтобы доказать, что группа с выражением CASE работает, а не убедить вас жестко запрограммировать значения book_conf. - person Rob van Wijk; 15.04.2011

select pub_name,
(CASE   WHEN a.book_name in(SELECT BOOK FROM BOOK_CONF) THEN 'UNI'  
 WHEN a.book_name ='JAVA' THEN 'JAVA'    ELSE 'MIS'    END)  AS test,
count(*) from books a group by pub_name, test;

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

person reggie    schedule 14.04.2011
comment
Тестирование на 10g-XE, не работает: ORA-00904: "test" invalid identifier. IME, это относится к 9i и 10g — вы не можете использовать псевдонимы столбцов в GROUP BY для Oracle — ORDER BY — это самое раннее, когда вы можете использовать псевдонимы столбцов для Oracle. - person OMG Ponies; 14.04.2011

Поскольку a.book_name — это то, что вы тестируете внутри корпуса, это то, что вы должны иметь в группе:

select a.pub_name, (CASE WHEN a.book_name in (SELECT BOOK FROM BOOK_CONF) THEN 'UNI'   
                       WHEN a.book_name ='JAVA' THEN 'JAVA'    
                       ELSE 'MIS'    
                  END) test, count(*) 
from books a 
group by a.pub_name, a.book_name
person MacAnthony    schedule 14.04.2011
comment
+1: на 10g-XE подтверждено, что этот запрос будет выполняться без ошибок. Более важный вопрос заключается в том, вернет ли он ожидаемый результат. - person OMG Ponies; 14.04.2011
comment
Возможно, результаты не совсем такие, как ожидалось. Я тестировал только с реальным ограниченным случаем. - person MacAnthony; 14.04.2011
comment
-1, потому что он не дает результатов, которые пытается дать исходный запрос, и это неправда, что вы не можете группировать выражения по регистру. - person Rob van Wijk; 14.04.2011