CASES 内でいくつかのカウントを使用して、2 つのクエリ結果変数のランキング値を作成しています。
次のコードは、実際にはより大きなクエリ内の左外部結合であり、ご想像のとおり、処理が少し遅くなります。これを改善する方法はありますか?私は今、このコードを何時間も調べています。助けていただければ幸いです。
SELECT
U.id,
COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') AS leMatchesCount,
COALESCE(
(CASE
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') = 6 THEN 3.33
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') = 5 THEN 2.75
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') < 5 AND COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') >= 2 THEN 1.11
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') = 1 THEN 0.55
END)
, 0) AS leRank1,
IF(MATCH(C.assets_animal_name) AGAINST ("any animal" IN BOOLEAN MODE), 1.11,
COALESCE(
(CASE
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') = 6 THEN 1.11
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') = 5 THEN 0.88
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') < 5 AND COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') >= 2 THEN 0.37
WHEN COUNT(C.assets_animal_name REGEXP 'cats|dogs|birds|rats|horses|cows') = 1 THEN 0.18
END)
, 0)) AS leRank2
FROM
us3r U
LEFT OUTER JOIN assets_animals C ON
C.user_id = U.id AND C.assets_animal_name IN ('cats','dogs','birds','rats','horses','cows')
GROUP BY
U.id
編集1:
クエリはオンザフライで作成され、ランキングに使用されるパラメーターの数がわかりません。
CASE 内では、4 つの WHEN 行のそれぞれが動的な数値 (ここでは 6) との一致を試み、各一致を次のように評価します (計算はサーバー側で行われ、これは論理出力です)。
WHEN = 6 rank = 5.00
WHEN = (6-1) rank = 3.80
WHEN < (6-1) AND > 2 = 2.90
WHEN = 1 rank = 1.11
3 行目で、コードは"<"以前の値 BUT ">" 2をチェックすることに注意してください。
Ross Smith IIが指摘したように、WHEN の外で COUNT を使用すると、WHEN 内で「<」などのオペランドを使用できなくなります。
最初の 2 つと最後の WHEN については、比較記号は必要ありません。つまり、10 ではなく 6 カウントできるので、各 CASE は次のようになります。
COALESCE(
(CASE COUNT(C.assets_animal_name IN ('cats','dogs','birds','rats','horses','cows'))
WHEN 6 THEN 3.33
WHEN 5 THEN 2.75
WHEN COUNT(C.assets_animal_name IN ('cats','dogs','birds','rats','horses','cows') < 5 AND COUNT(C.assets_animal_name IN ('cats','dogs','birds','rats','horses','cows') >=2 THEN 1.11
WHEN 1 THEN 0.55
END)
, 0) AS leRank1,
この単純な変更により、貴重な数ミリ秒が節約されました。ありがとう。
編集2:
つかれた。「WHEN の外で COUNT を使用すると、WHEN 内でオペランドを使用することはできません」と書きました。つまり、上記の例では、一致するレコードが 0 件の場合に 3 行目が true になることを意味します。
編集3:
C structure: id(INT,P),assets_animal_name(VARCHAR), uid(FK->U)
U structure: id(INT,P), email(VARCHAR)
サンプルデータ:
C
1,cats,1
2,dogs,1
3,birds,1
4,birds,2
5,rats,2
6,horses,2
7,cows,2
8,cats,2
U
1, jdoe@aol.com
2, mjoe@aol.com
REGEXP '^(cats|dogs|birds|rats|horses|cows)$' の結果データ:
1, 5, 2.75, 0.88
2, 3, 1.11, 0.37