Выберите сумму из двух объединенных таблиц - PullRequest
0 голосов
/ 24 сентября 2018

Есть структуры:

CREATE TABLE `invoices` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `invoices` VALUES (1,'2018-09-22');

CREATE TABLE `products` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`invoice_id` int(10) unsigned NOT NULL,
`amount` decimal(10,2) unsigned NOT NULL,
`quantity` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `products` VALUES (1,1,150.00,2),(2,1,60.00,3),(3,1,50.00,1);

CREATE TABLE `payments` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`invoice_id` int(10) unsigned NOT NULL,
`amount` decimal(10,2) unsigned NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `payments` VALUES (1,1,400.00,'2018-09-23'),(2,1,80.00,'2018-09-23');

У меня есть этот запрос:

select i.id, sum(pr.amount * pr.quantity) as productAmount, 
sum(pm.amount) as paymentAmount
from invoices as i
left join products as pr on pr.invoice_id=i.id
left join payments as pm on pm.invoice_id=i.id
group by i.id

, и у меня есть такой результат:

+----+---------------+---------------+
| id | productAmount | paymentAmount |
+----+---------------+---------------+
|  1 |       1060.00 |       1440.00 |
+----+---------------+---------------+
1 row in set (0,00 sec)

Однако я хочу получитьследующий результат:

+----+---------------+---------------+
| id | productAmount | paymentAmount |
+----+---------------+---------------+
|  1 |        530.00 |        480.00 |
+----+---------------+---------------+
1 row in set (0,00 sec)

Я хочу сумму суммы продуктов и сумму платежей, сгруппированных по invoice.id.
Каким должен быть запрос в этом случае?

Ответы [ 4 ]

0 голосов
/ 24 сентября 2018

Я могу представить себе ситуацию, когда создается счет-фактура, создаются продукты, но нет платежа, аналогично создается счет-фактура, создается платеж, но продуктов нет. Так что вы можете создавать подзапросы для продуктов и платежей

drop table if exists i,pr,pm;
CREATE TABLE `i` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `i` VALUES (1,'2018-09-22'),(2,'2018-09-22'),(3,'2018-09-22'),(4,'2018-09-22');

CREATE TABLE `pr` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`invoice_id` int(10) unsigned NOT NULL,
`amount` decimal(10,2) unsigned NOT NULL,
`quantity` smallint(5) unsigned NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `pr` VALUES (1,1,150.00,2),(2,1,60.00,3),(3,1,50.00,1),(4,3,50.00,1);

CREATE TABLE `pm` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`invoice_id` int(10) unsigned NOT NULL,
`amount` decimal(10,2) unsigned NOT NULL,
`date` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB;

INSERT INTO `pm` VALUES (1,1,400.00,'2018-09-23'),(2,1,80.00,'2018-09-23'),(3,4,80.00,'2018-09-23');


select i.id, (select sum(pr.amount * pr.quantity) from pr where pr.invoice_id = i.id) as productAmount, 
                 (select sum(pm.amount) from pm where pm.invoice_id = i.id) as paymentAmount
from i
having productAmount > 0 or paymentAmount > 0;

Вы можете (или можете не хотеть иметь пункт)

+----+---------------+---------------+
| id | productAmount | paymentAmount |
+----+---------------+---------------+
|  1 |        530.00 |        480.00 |
|  3 |         50.00 |          NULL |
|  4 |          NULL |         80.00 |
+----+---------------+---------------+
3 rows in set (0.00 sec)
0 голосов
/ 24 сентября 2018

Я иногда сталкиваюсь с подобными вопросами.Из-за множественных объединений значения из конкретной таблицы дублируются, дублируются и т. Д. Чтобы исправить это, я обычно делаю небольшой взлом, разделяя сумму (в конкретной таблице ) на количество различных Id (s).) из таблицы прочее .Это сводит на нет эффект множественных дубликатов.

Попробуйте выполнить следующий запрос:

select i.id, 
       (sum(pr.amount * pr.quantity) / IF(count(distinct pm.id) > 0, count(distinct pm.id), 1) as productAmount, 
       (sum(pm.amount) / IF(count(distinct pr.id) > 0, count(distinct pr.id), 1) as paymentAmount
from invoices as i
left join products as pr on pr.invoice_id=i.id
left join payments as pm on pm.invoice_id=i.id
group by i.id
0 голосов
/ 24 сентября 2018

Используйте приведенный ниже подзапрос, чтобы получить ожидаемый результат

SELECT id, 
(select sum(pr.amount * pr.quantity) from products as pr where pr.invoice_id=i.id ) as productAmt, 
(select sum(amount) from payments where invoice_id=i.id ) as PaymentAmt 
FROM `invoices` i order by id asc
0 голосов
/ 24 сентября 2018

Попробуйте это: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=3b496214bf0ffb517dcaa9be7f0b6bb7

select a.id,pramount,sum(amount) as paymentamount from 
(select i.id,sum(pr.amount *pr.quantity) as pramount
from invoices as i
join products as pr on pr.invoice_id=i.id
group by i.id)a
join payments pm on a.id=pm.invoice_id
group by a.id
...