1つの共通列の製品テーブルに結合された、非一意のトランザクションIDを持つテーブルをフィルタリングしようとしています。フィルターは次のようにする必要があります。
equal to :group1 AND
NOT equal to :group2 AND
NOT equal to :group3
私はもともと以下のクエリから始めましたが、AND rk_group <> ____
条件。
SELECT COUNT(DISTINCT txn_id)
FROM 1_txns
INNER JOIN 2_products USING (sku)
WHERE rk_group = :group1
AND rk_group <> :group2
AND rk_group <> :group3
;
私も試しました
SELECT COUNT(DISTINCT txn_id)
FROM 1_txns
INNER JOIN 2_products USING (sku)
WHERE rk_group NOT IN ( :group2, :group3)
;
また、結合とIN()およびNOT IN()の複数の組み合わせを試しましたが、NOTグループが存在するものを含むすべてのチームIDが返されます。
誰かが私を正しい方向に向けることができますか?.
クエリに関連するスキーマ情報:
table 1_txns
(txn_id, sku)
table 2_products
(sku, rk_group)
サンプルデータ
Txn_id, rk_group
------
1,group1
1,group2
2,group1
3,group1
3,group3
上記が私のデータであり、group1がmy =グループで、groups2と3が!=グループである場合、行カウント1を返す必要があります。これは、txn id '2'です。これまでに試したすべてのメソッドは、3のカウントを返します。
注:2_productsテーブルには、3つの異なるrk_groupしかありません。
WHERE句は各行に個別に適用され、同じ値がa
と等しく、同時にb
と等しくないかどうかを確認しても意味がないため、あまり意味がありません。またはc
–もちろん、b
の場合、c
またはa
とは異なります。したがって、代わりに必要なのは、行のグループ全体に条件を適用することです。具体的には、共有する各行グループに同じ_txn_id
_。
したがって、GROUP BYを使用し、行のグループに条件を適用するにはHAVINGを使用する必要があります。このクエリは、要件に一致する_txn_id
_値のリストを提供します。
_SELECT
t.txn_id
FROM
1_txns AS t
INNER JOIN 2_products AS p USING (sku)
GROUP BY
t.txn_id
HAVING
COUNT(p.rk_group = :group1 OR NULL) > 0
AND COUNT(p.rk_group IN (:group2, group3) OR NULL) = 0
;
_
リストは必要ないようで、アイテムの数だけなので、上記を派生テーブルとして使用して行をカウントします。
_SELECT
COUNT(*)
FROM
(
SELECT
txn_id
FROM
1_txns AS t
INNER JOIN 2_products AS p USING (sku)
GROUP BY
t.txn_id
HAVING
COUNT(rk_group = :group1 OR NULL) > 0
AND COUNT(rk_group IN (:group2, group3) OR NULL) = 0
) AS s
;
_
ご覧のとおり、COUNT(DISTINCT ...)
は必要ありません。派生テーブルは_txn_id
_でグループ化されているため、重複を返すことができません。したがって、正しい結果を得るにはCOUNT(*)
で十分です。
この答えで詳しく説明されているように、気づかない場合は、_OR NULL
_ビットを使用すると、COUNT関数で一致のみをカウントし、不一致を除外できます。
現在の実装の問題は、同じsku/txnsに一致する他の行を表示していないが、そのsku/txnsに一致する別の行に異なるrk_groupがあることだと思います。
_SELECT
i.sku,
i.GoodGroup as rk_group
FROM (
SELECT
A.sku as sku,
B.rk_group as GoodGroup,
COUNT(C.rk_group) as cnt
FROM
1_txns as A
INNER JOIN 2_products as B
ON A.sku=B.sku
AND B.rk_group = :group1 --should eliminate anything that isn't in group 1. If MySQL complains about a constant here, drop it to the `WHERE` clause
LEFT JOIN 2_products as C
ON A.sku=C.sku
AND B.rk_group <> C.rk_group --don't repeat the same entry as previous. This is redundant given the current WHERE clause
GROUP BY
A.sku, B.rk_group
WHERE
C.rk_group IN (:group2, :group3)
) as i
WHERE
i.cnt < 1
_
別のレイヤーをその周りにラップしてSELECT COUNT( *stuff from above* )
で、必要なエントリ数を取得できます。