2013-10-24 1 views
2

Долгое название и странная проблема: Я хочу использовать оператор with в oracle SQL для повторного использования подзапроса, а также в select as group by. Кроме того, я использую оператор case, чтобы создать дополнительную информацию и сгруппировать результаты. Это утверждение, однако, вызывает следующую ошибку: ORA-00979: не выражение GROUP BY.Oracle SQL использует подзапрос симулятивно в группе с помощью & select предложений в сочетании с оператором CASE

Пример запроса, который не работает: я определяю запрос, содержащий сумму продаж для каждого семейства продуктов. Я сортирую этот запрос и выбираю самую продаваемую семейство продуктов, если это так. В качестве основного результата я хочу сравнить эту самую продаваемую семью с суммой продаж других семейств продуктов (не один за другим, а всех других семейств продуктов, сгруппированных вместе). Я делаю это следующим образом:

WITH 
top_family AS (
SELECT * 
FROM (SELECT c.family 
     FROM products c, sales d 
     WHERE c.product_id= d.product_id 
     GROUP BY c.family 
     ORDER BY SUM(d.quantity) DESC) 
     WHERE ROWNUM = 1) 

SELECT CASE 
      WHEN a.family IN (SELECT * FROM top_family) 
      THEN 'Most sold category' 
      ELSE 'Other categories' 
     END Family, SUM(a.price*b.quantity) "Total monetary sales" 
FROM products a, sales b 
WHERE a.product_id = b.product_id 
GROUP BY CASE 
      WHEN a.family IN (SELECT * FROM top_family) 
      THEN 'Most sold category' 
      ELSE 'Other categories' 
     END 
ORDER BY 1; 

Интересным фактом является то, что если я заменить суб-запроса «top_family», как определено в приведенном выше коде непосредственно в коде (так заменить каждое каждое место, содержащее top_family с выбора * из (select ...)), он работает и дает желаемый результат.

Проблема, вероятно, должна быть вызвана использованием подзапроса, определенного в инструкции a. Хотя я понимаю, что есть (более качественные и более элегантные) решения, чем этот, я хотел бы узнать, почему я не могу использовать псевдоним таблицы «top_family» в группе по и выбрать оператор.

+0

Что делать, если есть несколько наиболее продаваемых семей? Вы выбираете только один из них, ограничивая ROWNUM. – Rachcha

+0

@ Rachcha, это совершенно верно. Наверное, я делаю абстракцию того факта, что действительно возможно, что есть несколько семей, которые продают самые продаваемые. – Drizzt

+0

Знаете ли вы, что если вы переписываете запрос, чтобы не использовать оператор with (то есть, скопировав запрос в инструкции with, где у вас есть top_family), он все еще не работает в Oracle 10g? Ваше требование действительно имеет место, хотя в 12c. – mvherweg

ответ

0

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

WITH 
top_product AS (
    SELECT s1.product_id 
    FROM sales s1 
GROUP BY s1.product_id 
    HAVING sum(s1.quantity) 
      = (SELECT total_sale 
       FROM (SELECT SUM(s.quantity) AS total_sale 
         FROM sales s 
        GROUP BY s.product_id 
        GROUP BY SUM(s.quantity)) 
       WHERE rownum = 1)) 

    SELECT CASE t.product_id 
      WHEN null THEN 'Other categories' 
      ELSE 'Most sold category' 
     END Family, 
     SUM(a.price*b.quantity) "Total monetary sales" 
    FROM products a JOIN sales b 
     ON a.product_id = b.product_id 
     LEFT JOIN top_product t ON a.product_id = t.product_id 
GROUP BY CASE t.product_id 
      WHEN null THEN 'Other categories' 
      ELSE 'Most sold category' 
     END 
ORDER BY 1; 
+0

Как ни странно, в этом коде отсутствует правая скобка где-то в предложении with. Я немного изменил свои вопросы: знаете ли вы, почему мой код не работает? – Drizzt

+0

Ну, в этом случае вы имеете правильную скобку перед основным оператором SELECT. – Rachcha

1

Проблема находится в GROUP BY CASE WHEN заявлении.

Этот оператор компилируется только на последнем этапе выполнения. Таким образом, этот подпункт от SELECT CASE WHEN. Эта нулевая операция возвращает ошибки.

Он также описан в руководстве по SQL.

Смежные вопросы