Почему эта функция не создается? - PullRequest
0 голосов
/ 03 апреля 2020

Попытка создать функцию, которая занимает месяц (1-12) и возвращает идентификатор продукта, который имеет самые высокие продажи (qtyordered * котировочная цена). Ошибка: PL / SQL: ORA-00936: отсутствует выражение, полученное из подзапроса в предложении where. Я предполагаю, что это единственная ошибка с этой функцией, но я не могу заставить этот подзапрос работать.

Новый для SQL, поэтому я прошу прощения, если это что-то супер очевидное. Использование Oracle.

CREATE OR REPLACE FUNCTION get_monthly_sales (month_num IN NUMBER)
RETURN NUMBER IS 
    p_id NUMBER(10,0) := 0;
BEGIN 
    SELECT productid INTO p_id
    FROM order_details ods INNER JOIN orders o
        ON ods.orderid = o.id
    WHERE (SELECT MAX(SUM(qtyordered * quotedprice)) FROM order_details)
    AND EXTRACT(MONTH FROM orderdate) = month_num;
RETURN p_id;
END;

РЕДАКТИРОВАТЬ: я добавил ключевое слово IN в предложение WHERE, что позволило создать функцию, но теперь возвращает следующую ошибку: ORA-00978: функция вложенной группы без GROUP BY .

WHERE p_id IS 
        (SELECT MAX(SUM(qtyordered * quotedprice)) FROM order_details)
    AND EXTRACT(MONTH FROM orderdate) = month_num;

Ответы [ 2 ]

0 голосов
/ 03 апреля 2020

Вы правы, что ваша проблема в предложении WHERE. Тем не менее, я не могу понять, что вы пытаетесь сделать, поэтому вам трудно дать вам совет.

У вас есть

WHERE (SELECT MAX(SUM(qtyordered * quotedprice)) FROM order_details) ...

Проблема в том, что (SELECT MAX(SUM(qtyordered * quotedprice)) FROM order_details) не является логическим значением выражение - оно не может стоять само по себе в предложении WHERE. Кроме того, использование функции SUM подразумевает, что вы пытаетесь что-то сгруппировать, потому что SUM (как здесь показано) является функцией группировки - но в вашем подзапросе нет выражения GROUP BY, и, похоже, не имеет смысла иметь его.

Кроме того, я не уверен, что вы действительно хотите передать MONTH_NUM в качестве параметра и использовать его таким, какой вы есть. Допустим, вы передаете 4 как MONTH_NUM, что означает «апрель». То, как вы написали свою функцию (при условии, что запрос работает), вы соберете вместе данные за апрель 2018 года, апрель 2019 года, апрель 2020 года и т. Д. c, и c. Я сомневаюсь, что ты этого хотел. Возможно, вы хотите передать дату и урезать ее до уровня месяца. Так что, возможно, вы ищете

CREATE OR REPLACE FUNCTION GET_MONTHLY_SALES(pin_Month IN DATE)
  RETURN NUMBER
IS
  nTotal_monthly_sales  NUMBER; 
BEGIN 
  SELECT SUM(od.QTYORDERED * od.QUOTEDPRICE)
    INTO nTotal_monthly_sales
    FROM ORDER_DETAILS od
    INNER JOIN ORDERS o
      ON o.ID = od.ORDERID
    WHERE TRUNC(o.ORDERDATE, 'MONTH') = TRUNC(pin_Month, 'MONTH');

  RETURN nTotal_monthly_sales;
END GET_MONTHLY_SALES;

Это должно (если я угадал, в каких таблицах правильно расположены различные поля) должно получиться общее количество продаж за месяц, соответствующее дате ввода, которая выглядит соответствовать названию функции.

РЕДАКТИРОВАТЬ

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

CREATE OR REPLACE FUNCTION FIND_PRODUCT_WITH_MAX_SALES(pinMonth IN NUMBER)
  RETURN NUMBER
IS
BEGIN
  IF pinMonth BETWEEN 1 AND 12 THEN
    FOR aRow IN (SELECT od.PRODUCT_ID,
                        SUM(od.QTYORDERED * od.QUOTEDPRICE) AS TOTAL_MONTHLY_SALES
                   FROM ORDER_DETAILS od
                   INNER JOIN ORDERS o
                     ON o.ID = od.ORDERID
                   WHERE TO_NUMBER(TO_CHAR(o.ORDERDATE, 'MM')) = pinMonth
                   GROUP BY od.PRODUCT_ID
                   ORDER BY SUM(od.QTYORDERED * od.QUOTEDPRICE) DESC)
    LOOP
      RETURN aRow.TOTAL_MONTHLY_SALES;
    END LOOP;
  ELSE
    RAISE_APPLICATION_ERROR(-20001, 'FIND_PRODUCT_WITH_MAX_SALES: Error - pinMonth (' || 
                                    pinMonth || ') not in range 1..12'); 
  END IF;
END FIND_PRODUCT_WITH_MAX_SALES;
0 голосов
/ 03 апреля 2020

Попробуйте это

  Select productid INTO p_id 
    from(SELECT productid 

   FROM order_details ods INNER JOIN 
    orders o
    ON ods.orderid = o.id

 WHERE 
EXTRACT(MONTH FROM orderdate) 
= month_num 
order by (qtyordered * quotedprice)
Desc) where rownum=1
...