MySQLは、異常な結果を出すことで、多くのものとグループをグループにします
-
12-10-2019 - |
質問
私は次のかなり簡単なセットアップに困難を抱えています:
CREATE TABLE IF NOT EXISTS invoices (
id int(11) NOT NULL auto_increment,
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS invoices_items (
id int(11) NOT NULL auto_increment,
invoice_id int(11) NOT NULL,
description text NOT NULL,
amount decimal(10,2) NOT NULL default '0.00',
PRIMARY KEY (id)
);
CREATE TABLE IF NOT EXISTS invoices_payments (
id int(11) NOT NULL auto_increment,
invoice_id int(11) NOT NULL,
amount decimal(10,2) NOT NULL default '0.00',
PRIMARY KEY (id)
);
いくつかのデータ:
INSERT INTO invoices (id) VALUES (1);
INSERT INTO invoices_items (id, invoice_id, description, amount) VALUES
(1, 1, 'Item 1', '750.00'),
(2, 1, 'Item 2', '750.00'),
(3, 1, 'Item 3', '50.00'),
(4, 1, 'Item 4', '150.00');
INSERT INTO invoices_payments (id, invoice_id, amount) VALUES
(1, 1, '50.00'),
(2, 1, '1650.00');
そして、SQLが異常な結果をもたらします:
select invoices.id,
ifnull(sum(invoices_payments.amount),0) as payments_total,
ifnull(count(invoices_items.id),0) as item_count
from invoices
left join invoices_items on invoices_items.invoice_id=invoices.id
left join invoices_payments on invoices_payments.invoice_id=invoices.id
group by invoices.id
(誤った)出力が得られます
id payments_total item_count
1 6800.00 8
さて、インクラクトが4つしかないことから証明されているように、「Invoice_Item」行は4つだけであるため、なぜMySQLが適切にグループ化していないのかわかりません。
編集
私はこのようなことができることを知っています:
select x.*, ifnull(sum(invoices_payments.amount),0) as payments_total from (
select invoices.id,
ifnull(count(invoices_items.id),0) as item_count
from invoices
left join invoices_items on invoices_items.invoice_id=invoices.id
group by invoices.id
) as x left join invoices_payments on invoices_payments.invoice_id=x.id
group by x.id
しかし、私は最初のクエリで何か間違ったことをしているかどうかを知りたいです - 最初のクエリが誤った結果を与えている理由をすぐに見ることができません! :(
解決
参加ロジックが正しくありません。 Joinで、Invoices_items.invoice_id = Invoices.idを指定します。また、Invoices_Payments.invoice_id = Invoices.idを指定します。推移性のため、あなたは次のことになります:
invoices_items.invoice_id = invoices.id
invoices_payments.invoice_id = invoices.id
invoice_items.invoice_id = invoices_payments.invoice_id
2つの請求書支払いの合計は1700ドルです。請求書の支払いごとに、上記の関係を満たす4つのInvoice_Itemがあります。 $ 1700 * 4 = $ 6800。
請求書ごとに、上記の関係を満たす2つの請求書支払いがあります。 4つの請求書アイテム * 2 = 8カウント。
他のヒント
多くのテーブルがあります。1つは請求書との関係です。あなたのカウントはデカルト製品です。
支払いは、請求書項目ではなく、請求書に適用する必要があります。最初に請求書の合計を取得してから、支払いに参加してください。
これはあなたが探しているものに似ているかもしれません:
SELECT
invoice_total.invoice_id,
invoice_total.amount as invoice_amount,
payments_total.amount as total_paid
FROM
(
SELECT
invoice_id,
SUM(amount) as amount
FROM
invoices_items
GROUP BY
invoice_id
) invoice_total
INNER JOIN
(
SELECT
invoice_id,
SUM(amount) as amount
FROM
invoices_payments
GROUP BY
invoice_id
) payments_total
ON invoice_total.invoice_id = payments_total.invoice_id;
編集:
ああ、ごめんなさい - 今あなたのポイントを見てください。予期しない結果が得られる理由は、このクエリが次のとおりです。
SELECT *
FROM invoices
LEFT JOIN invoices_items ON invoices_items.invoice_id = invoices.id
LEFT JOIN invoices_payments ON invoices_payments.invoice_id = invoices.id;
結果:
id id invoice_id description amount id invoice_id amount
1 1 1 Item 1 750.00 1 1 50.00
1 1 1 Item 1 750.00 2 1 1650.00
1 2 1 Item 2 750.00 1 1 50.00
1 2 1 Item 2 750.00 2 1 1650.00
1 3 1 Item 3 50.00 1 1 50.00
1 3 1 Item 3 50.00 2 1 1650.00
1 4 1 Item 4 150.00 1 1 50.00
1 4 1 Item 4 150.00 2 1 1650.00
あなたが見ることができるように、あなたはすべてを手に入れます invoices_items
毎回1回記録します invoices_payments
記録。個別に(つまり、グループ)をつかまなければなりません。
に注意してください GROUP BY
最初のクエリの節は冗長です。
これが必要なものです:
SELECT
invoices.id,
payments_total.payments_total,
IFNULL(COUNT(invoices_items.id),0) AS item_count
FROM invoices
LEFT JOIN invoices_items ON invoices.id = invoices_items.invoice_id
LEFT JOIN (
SELECT invoice_id,
IFNULL(SUM(invoices_payments.amount),0) AS payments_total
FROM invoices_payments
GROUP BY invoice_id
) AS payments_total ON invoices.id = payments_total.invoice_id
;