MySQLは、異常な結果を出すことで、多くのものとグループをグループにします

StackOverflow https://stackoverflow.com/questions/4731816

  •  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
;
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top