Более 1 строки возвращено из SELECT внутри SELECT - PullRequest
1 голос
/ 15 марта 2020

Я пытаюсь создать запрос, чтобы узнать, какова общая сумма задолженности каждого клиента перед компанией. Это - GROUP BY customerNumber в подзапросе, который создает проблему.

SELECT customerName,
       customers.customerNumber,
       SUM(quantityOrdered * priceEach) - ( SELECT SUM(amount) AS MoneyPayed FROM payments GROUP BY customerNumber ) AS AmountOwed
FROM payments
INNER JOIN customers ON payments.customerNumber = customers.customerNumber
INNER JOIN orders ON customers.customerNumber = orders.customerNumber
INNER JOIN  orderdetails ON  orders.orderNumber = orderdetails.orderNumber
GROUP BY customerNumber;

Таблицы, которые я пытаюсь связать: payments и orderdetails.

Когда я избавиться от GROUP BY Я получаю результаты в отрицательных значениях, так как из каждой строки SUM(quantityOrdered * priceEach) вычитается сумма SUM суммы. Как это изменить, чтобы я мог возвращать несколько строк из платежей вычесть из SUM(quantityOrdered * priceEach) из таблицы деталей заказа.

Ссылка на БД, так как StackOverflow не позволяет мне публиковать изображения

https://i.stack.imgur.com/N6o1w.png

Спасибо за помощь, извините, если формат плохой, это мой первый пост.

1 Ответ

0 голосов
/ 15 марта 2020

Вам понадобится пара подзапросов, чтобы удовлетворить ваши требования. Давайте разберемся с этим.

Во-первых, вам нужна общая стоимость заказов от каждого клиента. Вы очень близки к правильному запросу для этого. Это должно быть

               SELECT orders.customerNumber,
                      SUM(orderdetails.quantityOrdered * orderdetails.priceEach) owed
                 FROM orders
                 JOIN orderdetails ON  orders.orderNumber = orderdetails.orderNumber
             GROUP BY orders.customerNumber

Этот результирующий набор подзапроса дает customerNumber и задолженность, причитающуюся сумму. Обратите внимание, что orders :: orderdetails является отношением one :: many, поэтому мы уверены, что мы учитываем каждую деталь только один раз, поэтому суммы SUM будут правильными.

Далее нам нужна сумма, выплачиваемая каждым клиентом. , Этот подзапрос довольно прост.

               SELECT customerNumber,
                      SUM(amount) paid
                 FROM payments
                GROUP BY customerNumber

Теперь для операции, которая вам не хватает в вашем вопросе: нам нужно присоединить эти два подзапроса к таблице ваших клиентов.

SELECT customers.customerName, customers.customerNumber
       owed.owed - paid.paid balance
  FROM customers
  LEFT JOIN (
               SELECT orders.customerNumber,
                      SUM(orderdetails.quantityOrdered * orderdetails.priceEach) owed
                 FROM orders
                 JOIN orderdetails ON  orders.orderNumber = orderdetails.orderNumber
             GROUP BY orders.customerNumber
       ) paid ON customers.customerNumber = paid.customerNumber
  LEFT JOIN (
               SELECT customerNumber,
                      SUM(amount) paid
                 FROM payments
                GROUP BY customerNumber
       ) owed ON customers.customerNumber = owed.customerNumber

Посмотрите, как это работает? Мы объединяем таблицу и два подзапроса. Каждый подзапрос имеет либо ноль, либо одну строку для каждой строки в таблице, поэтому нам не нужно использовать SUMs или GROUP BY во внешнем запросе.

Осталось только одно осложнение: что, если клиент никогда ничего не платил? Тогда значение paid.paid будет равно NULL после операции LEFT JOIN. Это заставит значение owed - paid быть NULL. Поэтому нам нужно больше умов в операторе SELECT, чтобы получить правильные суммы.

SELECT customers.customerName, customers.customerNumber
       COALESCE(owed.owed,0) - COALESCE(paid.paid,0) balance
       ...

COALESCE (a, b) эквивалентно , если a не равно нулю, тогда a else b .

Pro tip В запросах или подзапросах с операциями JOIN всегда указывайте table.column вместо column. Следующий человек, который будет работать над вашим запросом, поблагодарит вас.

...