ORA-00934: групповая функция здесь не разрешена.Проблемы с WHERE SUM (x) = (ВЫБЕРИТЕ MIN (SUM (x))) - PullRequest
0 голосов
/ 18 мая 2019

Необходимо получить фамилию и имя клиента с наименьшим платежом. Платеж имеет различные счета-фактуры, разделенные на метод оплаты, поэтому мне нужно СУММИТЬ платежи с тем же номером счета, прежде чем я решу, какой платеж наименьший. Платеж и Клиент - это разные сущности / таблицы, связанные третьей, Счет-фактура. Отношения один-ко-многим между сущностями выглядят так:

Client -----<= Invoice ------<= Payment. 

SELECT c.first_name, c.last_name FROM client c, invoice i
wHERE i.id_client_fk1 = c.id_pk
AND i.num_pk = (SELECT num_invoice_fk1 
                FROM payment 
                WHERE SUM(amount_after_tax) = (SELECT MIN(SUM(amount_after_tax)) 
                                               FROM payment 
                                               GROUP BY num_pk));

У клиента PK используется в счете-фактуре как FK, а в счете-фактуре PK используется в качестве платежа как FK.

Я хочу использовать ту же логику, которую я вставил в код, но, очевидно, она должна работать. Нужно сравнить WHERE SUM(amount_after_tax) = SELECT MIN(SUM(amount_after_tax)).

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

 SELECT c.first_name, c.last_name FROM client c, invoice i
 WHERE i.id_client_fk1 = c.id_pk
 AND i.num_pk = (SELECT num_invoice_fk1 FROM payment
                 WHERE amount_after_tax = (SELECT MIN(SUM(amount_after_tax)) 
                 FROM payment
                 GROUP BY num_pk));

Этот код выполняется в SQL, но он не выполняет то, что я хочу, потому что он сравнивает только отдельные платежи с MIN(SUM(amount_after_tax)). Допустим, у меня есть 3 платежа за один счет. Мне нужно сложить их, чтобы иметь возможность сравнить их с MIN(SUM(amount_after_tax)). Также пытался использовать HAVING, и это не работает. Может быть, я неопытный. Пожалуйста, помогите

Payment Table

Entity Relationship Diagram

Ответы [ 2 ]

0 голосов
/ 18 мая 2019

Описываются оконные функции:

select c.first_name, c.last_name
from client c join
     (select i.id_client_fk1, i.num_pk, sum(p.amount_after_tax) as total_amount,
             row_number() over (order by sum(p.amount_after_tax) asc) as seqnum
      from invoice i join
           payment p
           on p.num_invoice_fk1 = i.num_pk
      group by i.id_client_fk1, i.num_pk
    ) ip
    on i.id_client_fk1 = c.id_pk
where seqnum = 1;

Подзапрос объединяет данные и использует row_number() для перечисления результатов.Внешний запрос затем вводит имена и выбирает первую строку.

Примечания:

  • Никогда не используйте запятые в предложении FROM.
  • Всегда используйте правильный, явный, стандартный JOIN синтаксис.
  • Логика здесь проста.Просто агрегируйте, чтобы вычислить сумму и вытащите первую строку.

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

Поскольку вам нужна только одна строка, вы также можете использовать rownum:

Всплывают оконные функции:

select c.first_name, c.last_name
from (select c.first_name, c.last_name,
             i.id_client_fk1, i.num_pk, 
             sum(p.amount_after_tax) as total_amount,
      from invoice i join
           payment p
           on p.num_invoice_fk1 = i.num_pk
           client c join
           on i.id_client_fk1 = c.id_pk
      group by i.id_client_fk1, i.num_pk
      order by total_amount asc
    ) ip
where rownum = 1;
0 голосов
/ 18 мая 2019

Вы должны использовать наличие для фильтра агрегированного результата (не где)

SELECT c.first_name, c.last_name 
FROM client c, invoice i
WHERE i.id_client_fk1 = c.id_pk
AND i.num_pk = (SELECT
     num_invoice_fk1 
    FROM payment HAVING SUM(amount_after_tax) = 
      (SELECT MIN(amount_after_tax) 
       FROM payment 
       GROUP BY num_pk)
 );
...