0

Actian PSQL v13 の場合:

2 つのテーブルを結合し、いくつかの条件で結果セットをフィルター処理しようとしています。1 つのテーブルは顧客の販売履歴です。もう 1 つのテーブルは、顧客を購入グループに関連付けます。すべての顧客が購入グループに属しているわけではないため、考えられるすべての販売履歴結果を取得するために左結合を実行しています。結果に購入グループ「SALREP」の誰かを含めたくありませんが、どの購入グループにも属さない顧客を表示したいと考えています。また、いわゆるパーツ「FREIGHT」は結果から除外されています。

私が抱えている問題は、グループ「SALREP」を除外すると、購入グループに含まれる顧客のみが選択されることです。購買グループに属さないすべての顧客が欠落しています。

「SALREP」のフィルターをコメントアウトしてこれをテストしたところ、結果セットには実際に購入グループに属していない顧客が含まれています。また、Actian PSQL がうるさい場合に備えて、別のフィルター アプローチを使用してみました。たとえば、!=not()<>;など、さまざまな「等しくない」方法を試しました。問題は解決しません。また、同じ問題でleft joinandを使用しました。left outer join

クエリは次のとおりです。

select T2.GROUP_CUST, T1.DATE_INVOICE, T1.SALESPERSON, T1.CUSTOMER, T1.PRODUCT_LINE, T1.PART, T1.DESCRIPTION, T1.QTY_SHIPPED, T1.EXTENSION 
from ORDER_HIST_LINE T1 
left join BUYING_GROUP T2 on T1.CUSTOMER=T2.CUSTOMER 
where DATE_INVOICE > '2019-06-13' and PART != 'FREIGHT'
and T2.GROUP_CUST != 'SALREP' 
and T1.CUSTOMER in ('ABC', 'DEF', 'GHI')
order by T1.CUSTOMER;

予想される結果セットには、2019 年 6 月 13 日以降に請求されたものはすべて含まれ、「FREIGHT」と呼ばれる部分は含まれず、「SALREP」と呼ばれるグループに顧客が含まれていません。ただし、実際の結果セットは不完全です。例えば:

CUSTOMER | GROUP_CUST | DATE_INVOICE  | PART   | etc.
-----------------------------------------------------
ABC      |  A12       |  2019-06-14   | WIDGET
DEF      |  A12       |  2019-06-14   | GEAR

基本的に、どの購買グループにも属さない顧客はすべて除外されます。

その部分をコメントアウトするand T2.GROUP_CUST != 'SALREP'と、期待される結果が見つかります。例えば:

CUSTOMER | GROUP_CUST | DATE_INVOICE  | PART   | etc.
-----------------------------------------------------
ABC      |  A12       |  2019-06-14   | WIDGET
DEF      |  A12       |  2019-06-14   | GEAR
GHI      |            |  2019-06-15   | WIDGET

そもそも購入グループから「SALREP」を削除する選択クエリへの左結合を作成することを考えていましたが、結果セットでそのグループから誰かを識別して削除することはできません。元。:left join (select * from BUYING_GROUP where GROUP_CUST != 'SALREP') T2

8/7/19 さらなる試み: MySQL v5.0.12 でも同じジレンマを見つけています。テーブルを結合したままにしておくと、一致しない結果が得られます。予想外に何も失うことなく、これらの不一致の結果で左側のテーブルをフィルター処理できます。それでも、不一致の行をすべて消去せずに、これらの不一致の結果で正しいテーブルをフィルター処理することはできません。

4

2 に答える 2

0

https://mode.com/resources/sql-tutorial/sql-joins-where-vs-on/に感謝します。この記事では、「WHERE 句でフィルター処理を行うと null 値もフィルター処理できるため、null を確実に含めるように行を追加しました」と記載されています。

これにより、正しいテーブルに対してフィルタリングするときに、そのフィルタリングされた列の NULL 値 (一致しない行) が含まれることを明示的に述べる必要があることをテストして認識しました。そうしないと、それらの一致しない行が結果セットから削除されます。また、フィルターのペアを括弧で囲むか、結果セットを「爆発」させる必要があることもわかりました。私がテストしたところ、これは正しいテーブルに対してフィルタリングする場合にのみ必要であることがわかりました。左のテーブルに対するフィルタリングには、この問題はありません (明らかに)。

最終的な答え:

select T2.GROUP_CUST, T1.DATE_INVOICE, T1.SALESPERSON, T1.CUSTOMER, T1.PRODUCT_LINE,             
T1.PART, T1.DESCRIPTION, T1.QTY_SHIPPED, T1.EXTENSION 
from ORDER_HIST_LINE T1 
left join BUYING_GROUP T2 on T1.CUSTOMER=T2.CUSTOMER 
where DATE_INVOICE > '2019-06-13' and PART != 'FREIGHT' 
and (T2.GROUP_CUST != 'SALREP' or T2.GROUP_CUST is null) 
and T1.CUSTOMER in ('ABC', 'DEF', 'GHI') 
order by T1.CUSTOMER;

行に注意してくださいand (T2.GROUP_CUST != 'SALREP' or T2.GROUP_CUST is null)

于 2019-08-07T19:43:42.060 に答える