反復クエリの開発...
あなたがproduct
テーブルを持っている、とだけcustomer_country_product
テーブルを持っていない場合、あなたはそれぞれの国のための製品の明確なリストを作成するために、インライン・ビューを使用することができます。
SELECT ccp.product_id
, ccp.country_id
FROM customer_country_product ccp
GROUP
BY ccp.product_id
, ccp.country_id
我々はそれインライン・ビューすることにより、値集合ソースとしてそのクエリを使用することができます...国によって製品を得るために。そのクエリを括弧で囲み、エイリアスを割り当て、別のクエリのFROM句で参照します。製品のペアを取得するには、同じ製品(A_A
)のペアを返さずに、「重複」ペアを返さないようにする(A_C
とC_A
のいずれかを返す)ことなくインラインビューを結合することができます。
SELECT a.country_id
, a.product_id AS a_product_id
, b.product_id AS b_product_id
FROM (SELECT ccpa.product_id
, ccpa.country_id
FROM customer_country_product ccpa
GROUP
BY ccpa.product_id
, ccpa.country_id
) a
JOIN (SELECT ccpb.product_id
, ccpb.country_id
FROM customer_country_product ccpb
GROUP
BY ccpb.product_id
, ccpb.country_id
) b
ON b.country_id = a.country_id
AND b.product_id > a.product_id
ORDER
BY a.country_id
, a.product_id
, b.product_id
各国のすべての商品の「ペア」を取得する必要があります。注:これは、製品を持つ顧客がいない製品を省略します。我々はすべての可能な製品のペアをしたい場合は、それぞれの国のために、我々はあなたがproduct
とcountry
テーブルを持っている場合は、上記のクエリでインライン・ビューを置き換えることができ少し違った...
SELECT c.country_id
, a.product_id AS a_product_id
, b.product_id AS b_product_id
FROM (SELECT ccpa.product_id
FROM customer_country_product ccpa
GROUP BY ccpa.product_id
) a
JOIN (SELECT ccpb.product_id
FROM customer_country_product ccpb
GROUP BY ccpb.product_id
) b
ON b.product_id > a.product_id
CROSS
JOIN (SELECT ccpc.country_id
FROM customer_country_product ccpc
GROUP BY ccpc.country_id
) c
ORDER
BY c.country_id
, a.product_id
, b.product_id
ことを書く必要があると思いますこれらのテーブルへの参照が含まれています。
顧客の「カウント」を取得するには、SELECTリストに相関サブクエリを使用するか、SELECTリストで結合操作と集計を実行できます。 (私たちが注意しないなら合流して、生成し、「重複」をカウントする可能性があります。)
は、特定の製品を持っている特定の国に明確な顧客の数を取得するには
SELECT COUNT(DISTINCT ccp.customer_id) AS cnt_cust
FROM customer_country_product ccp
WHERE ccp.country_id = ?
AND ccp.product_id = ?
は、2つの特定の製品を持っている特定の国に顧客の数を取得するには2つの特定の製品
SELECT COUNT(DISTINCT ccp.customer_id) AS cnt_cust_have_either
FROM customer_country_product ccp
WHERE ccp.country_id = ?
AND ccp.product_id IN (? , ?)
の少なくとも一つを有する特定の国からの明確な顧客の数を取得するには:
SELECT COUNT(DISTINCT ccp1.customer_id) AS cnt_cust_have_both
FROM customer_country_product ccp1
JOIN customer_country_product ccp2
ON ccp2.country_id = ccp1.country_id
AND ccp2.customer_id = ccp1.customer_id
WHERE ccp1.country_id = ?
AND ccp1.product_id = ?
AND ccp2.product_id = ?
これらのクエリは、単一の列を含む単一の行を返すため、これらを別のクエリのSELECTリストの式として使用できます。 「プロダクトペア」クエリから始め、SELECTリストに追加します。私たちは除算演算を行うために必要な「割合」を算出するために、今すぐ
SELECT c.country_id
, a.product_id AS a_product_id
, b.product_id AS b_product_id
, (SELECT COUNT(DISTINCT ccp1.customer_id)
FROM customer_country_product ccp1
JOIN customer_country_product ccp2
ON ccp2.country_id = ccp1.country_id
AND ccp2.customer_id = ccp1.customer_id
WHERE ccp1.country_id = c.country_id
AND ccp1.product_id = a.product_id
AND ccp2.product_id = b.product_id
) AS cnt_cust_have_both
, (SELECT COUNT(DISTINCT ccp.customer_id)
FROM customer_country_product ccp
WHERE ccp.country_id = c.country_id
AND ccp.product_id IN (a.product_id,b.product_id)
) AS cnt_cust_have_either
FROM (SELECT ccpa.product_id
FROM customer_country_product ccpa
GROUP BY ccpa.product_id
) a
JOIN (SELECT ccpb.product_id
FROM customer_country_product ccpb
GROUP BY ccpb.product_id
) b
ON b.product_id > a.product_id
CROSS
JOIN (SELECT ccpc.country_id
FROM customer_country_product ccpc
GROUP BY ccpc.country_id
) c
ORDER
BY c.country_id
, a.product_id
, b.product_id
:私たちは、外側のクエリからの列を参照して、それらの疑問符プレースホルダを交換してください。 MySQLでは、「ゼロによる除算」はNULLを返します。私たちの外側のクエリが行のみを返した場合、我々は国からの顧客を知っている(私たちは、それと気にする必要はありません持っている製品の1 ...最初のクエリ
SELECT c.country_id
, a.product_id AS a_product_id
, b.product_id AS b_product_id
, (SELECT COUNT(DISTINCT ccp1.customer_id)
FROM customer_country_product ccp1
JOIN customer_country_product ccp2
ON ccp2.country_id = ccp1.country_id
AND ccp2.customer_id = ccp1.customer_id
WHERE ccp1.country_id = c.country_id
AND ccp1.product_id = a.product_id
AND ccp2.product_id = b.product_id
)
/(SELECT COUNT(DISTINCT ccp.customer_id)
FROM customer_country_product ccp
WHERE ccp.country_id = c.country_id
AND ccp.product_id IN (a.product_id,b.product_id)
)
* 100.00 AS percent_cust_have_both
FROM (SELECT ccpa.product_id
FROM customer_country_product ccpa
GROUP BY ccpa.product_id
) a
JOIN (SELECT ccpb.product_id
FROM customer_country_product ccpb
GROUP BY ccpb.product_id
) b
ON b.product_id > a.product_id
CROSS
JOIN (SELECT ccpc.country_id
FROM customer_country_product ccpc
GROUP BY ccpc.country_id
) c
ORDER
BY c.country_id
, a.product_id
, b.product_id
によって返される結果すなわち私たちは適切なインデックスを用意しておく必要があります。特に相関サブクエリの場合は、になります。の行がすべて外側のクエリによって返されます。
最後のクエリは、分母にゼロのカウントがあるときにNULLを返す可能性があります。condで指定した除算をラップすることでゼロを代入することができますitionalテスト
IFNULL(<expr> , 0) * 100.00 AS
(多分エラーがどこかにこれらのクエリであります、行方不明括弧、無効な参照、間違った修飾子など、これらのクエリがテストされていません。私は強くあなたが各1テストし、ちょうどその最後の1をつかんいないお勧めします。)
フォロー
テスト用のテーブル...
CREATE TABLE customer_country_product
(customer_id INT
, country_id VARCHAR(2)
, product_id VARCHAR(2)
)
;
INSERT INTO customer_country_product (customer_id, country_id, product_id) VALUES
('1','US','A')
,('1','US','B')
,('2','CA','A')
,('2','CA','C')
,('3','US','A')
,('3','US','C')
,('4','US','B')
,('5','US','A')
;
最終クエリが返す:
country_id a_product_id b_product_id percent_cust_have_both
---------- ------------ ------------ ----------------------
CA A B 0.000000
CA A C 100.000000
CA B C 0.000000
US A B 25.000000
US A C 33.333333
US B C 0.000000
これは些細な変化は、単一の列にa.product_id
とb.product_id
を連結することになります。 SELECTリストの2番目と3番目の列は、CONCAT(a.product_id,'_',b.product_id) AS a_b
のようなものに置き換えることができます。
US A_Cの値は25%ではなく33%にする必要がありますか? 3人の顧客(1、3、5)がAまたはCのいずれかを購入し、そのうちの1つ(3)が両方を購入しました。 – APH
@APHあなたは正しいです。それは33%でなければなりません – Black