Код Sql возвращает неожиданные результаты. Как это исправить

Я использую Firebird 3. Есть главная таблица «sellers» для моих контрагентов, подробная таблица «Doc» для документов о доходах от товаров и подробная таблица «paym» для платежей.

Продавец: Seller_id, продавец
Документы: doc_id, doc_summa, part_id
Платеж: платный_ид, док_ид, платный

Продавец:

продавец_id продавец 8 Фирма1 45 Фирма2

Документы:

doc_id doc_summa продавец_id 346 1000 8 347 600 45 348 800 45

Оплата:

paym_id doc_id оплаченный 1 346 100 2 346 100 3 347 200 4 348 100 5 348 50

Моя цель - получить остаточные долги (выплату дохода) следующим образом:

продавец_id сумма оплаченный долг 8 1000 200 800 45 1400 350 1050

но получить это умноженные, неправильные суммы:

продавец_id сумма оплаченный долг 8 2000 г. 200 800 45 2200 350 1850 г.
SELECT
 s.seller_id, 
 sum(d.doc_summa) as summa,
 sum(p.paid) as paid,
 sum(d.doc_summa)-sum(p.paid) as debt

FROM seller s Left Join Docs d  on s.seller_id=d.seller_id
             Left Join  paym p  on p.doc_id= d.doc_id

GROUP BY s.seller_id

Что не так в моем коде SQL?

@Dai Real sql будет труден для восприятия из-за неанглийских названий таблиц и полей. Прежде чем я изменю там имена. Я исправляю selelr_id---->seller_id

basti 19.11.2022 09:29

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

mousetail 19.11.2022 09:35

@mousetail Я создаю новую базу данных. Есть ссылка на экран onedrive. 1drv.ms/u/s!AukGXPQiR2IpiPFjh_ad5pN8d3Q_aw?e=92yKsL

basti 19.11.2022 10:24

Это связано с тем, что в paym есть две записи для doc_id 346, поэтому есть две строки, и при суммировании получается 2000, то же самое для doc_id 348, в результате чего 800 учитываются дважды.

Mark Rotteveel 19.11.2022 11:01

Скрипка для воспроизведения: dbfiddle.uk/I5vDJatP

Mark Rotteveel 19.11.2022 11:02

@Dai Запрос действительно дает результат, который показывает OP, и он «правильный» (для данного запроса).

Mark Rotteveel 19.11.2022 11:03

Когда вы удалите функции sum и удалите GROUP BY, вы сможете определить, откуда берутся неправильные суммы. (см.: dbfiddle.uk/8A4T3w__) (600+800+800 = 2200)

Luuk 19.11.2022 11:13
Шаблоны Angular PrimeNg
Шаблоны Angular PrimeNg
Как привнести проверку типов в наши шаблоны Angular, использующие компоненты библиотеки PrimeNg, и настроить их отображение с помощью встроенной...
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Создайте ползком, похожим на звездные войны, с помощью CSS и Javascript
Если вы веб-разработчик (или хотите им стать), то вы наверняка гик и вам нравятся "Звездные войны". А как бы вы хотели, чтобы фоном для вашего...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Начала с розового дизайна
Начала с розового дизайна
Pink Design - это система дизайна Appwrite с открытым исходным кодом для создания последовательных и многократно используемых пользовательских...
Шлюз в PHP
Шлюз в PHP
API-шлюз (AG) - это сервер, который действует как единая точка входа для набора микросервисов.
14 Задание: Типы данных и структуры данных Python для DevOps
14 Задание: Типы данных и структуры данных Python для DevOps
проверить тип данных используемой переменной, мы можем просто написать: your_variable=100
1
7
63
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Проблема с вашим запросом заключается в том, что, поскольку существует несколько платежей для doc_id 346 и 348, у вас будет две строки с doc_summa 1000 и 800 соответственно, когда вы затем суммируете их, общая сумма становится 2000 для продавца_ид 8 и 2200 для продавца_ид 45 .

Чтобы решить эту проблему, вам необходимо консолидировать (суммировать) платежи перед присоединением к документам. Например, как следующее:

with consolidated_paym as (
  select 
    doc_id, 
    sum(paid) as total_paid
  from paym
  group by doc_id
)
select
  s.seller_id,
  sum(d.doc_summa) as summa,
  sum(p.total_paid) as paid,
  sum(d.doc_summa - p.total_paid) as debt
from seller s
left join docs d
  on d.seller_id = s.seller_id
left join consolidated_paym as p
  on p.doc_id = d.doc_id
group by s.seller_id

Рабочий пример: https://dbfiddle.uk/6_vyCu0w

Марк Роттевел, большое спасибо. Это работает правильно.

basti 20.11.2022 11:32

Другие вопросы по теме