1

where句を使用して3つのテーブルで左結合を実行しようとしていますが、機能させることができません。

私のテーブルは次のとおりです。

sale:
sale_id (int)
terminal_id (int)
zread_id (int)
... more fields about total amounts, dates times etc

sale_payment:
payment_id (int)
sale_id (int)
payment_type (enum: 'P','W','A')
method_id (int)
payment_amount (Decimal)

sale_writeoff_method:
method_id (int)
description (varchar)
display_order (int)

売上は、3つの異なる方法(したがって、列挙)で確定(支払い)できます。物理的な支払い-現金、小切手など、「償却」支払い-在庫が原価で使い果たされる場合(つまり、無駄、景品など)、またはアカウント-顧客クレジットなど

販売期間の終わり(1日の終わり)に、ユーザーはZ-Readを実行します。これにより、発生するすべてのトランザクションが収集され、レポートが生成されます。このレポートでは、ユーザーは引き出しなどの現金のバランスを取る必要があります。最初のZ-Readオブジェクト。クエリを使用して、必要な情報を収集できます。

SELECT m.method_id, m.description, SUM(s.sale_total) as z_total, COUNT(s.sale_id) as total_sales
FROM sale_writeoff_method m
LEFT JOIN sale_payment p ON m.method_id = p.method_id
LEFT JOIN sale s ON s.sale_id = p.sale_id 
WHERE s.zread_id IS NULL 
AND (p.payment_type = 'W' OR p.payment_type IS NULL) 
AND (s.terminal_id = ? OR s.terminal_id IS NULL) 
GROUP BY p.payment_type, m.method_id 
ORDER BY m.display_order;

すべてのバランスが取れて確定すると、salesテーブル内のすべてのタイプについて収集されたすべての売上に、このオブジェクトの挿入の結果であるzread_idのフラグが付けられます。

今の私の問題は、将来z-readオブジェクトを再作成する必要がある場合、たとえばレポートを再印刷するために、すべてのmethod_idと説明を表示することができないということです-私が使用しているクエリは:

SELECT m.method_id, m.description, SUM(s.sale_total) as z_total, COUNT(s.sale_id) as total_sales 
FROM sale_writeoff_method m 
LEFT JOIN sale_payment p ON m.method_id = p.method_id 
LEFT JOIN sale s ON s.sale_id = p.sale_id 
WHERE s.zread_id = 1 
AND (p.payment_type = 'W' OR p.payment_type IS NULL) 
GROUP BY p.payment_type, m.method_id 
ORDER BY m.display_order;

But it only displays methods that had sales attached for that Z-Read period. I can't use WHERE s.zread_id IS NULL because that will include all the sales that haven't been finalised yet.

任意の提案をいただければ幸いです!

4

1 に答える 1

2

問題は、一致する行が見つからない結合された列の値に対して左結合がnullを返すことですが、where句でそれらの列の値をチェックしていますが、where述語はすべての行が結合された後に実行されるため、決して一致すると、外部結合が沈みます。

つまり、このクエリの例:

select *
from table1 t1
left join table2 t2 on t2.fk = t1.id
where t2.col1 = 'x'

はに対応する行を持たない行を返すことありません。table2col1nullnullfalsecol1 is null

これを修正するには、テストを句に移動する必要があるため、次のように、結合が行われている間にON比較が行われます。

select *
from table1 t1
left join table2 t2 on t2.fk = t1.id and t2.col1 = 'x'

現在、左結合は、キーの照合中に行を返し、追加の述語を適用して一致をさらに絞り込みます。


あなたの場合、外部 (つまりleft) への結合を行っていますが、where 句でsale_payment pテストp.payment_type = 'W'しているため、機能しません。

ON句で行われた左結合テーブルのテストを含む固定クエリを次に示します。

SELECT
    m.method_id,
    m.description,
    SUM(s.sale_total) as z_total,
    COUNT(s.sale_id) as total_sales
FROM sale_writeoff_method m
LEFT JOIN sale_payment p ON m.method_id = p.method_id AND p.payment_type = 'W'
LEFT JOIN sale s ON s.sale_id = p.sale_id AND s.terminal_id = ?
GROUP BY m.method_id, m.description
ORDER BY m.display_order;

group by p.payment_typeその列を選択していないためも削除し、それm.description選択したためgroup by を追加したことに注意してください。

クエリを微調整する必要があるかもしれませんが、これがかなり近いものになることを願っています

于 2012-08-02T02:58:08.390 に答える