0

我在 CASES 中使用多个计数来为两个查询结果变量创建排名值。

下面的代码实际上是一个更大查询中的左外连接,正如您可能猜到的那样,它会减慢一点速度。有没有办法改善这一点?我已经完成了这个代码几个小时了,感谢您的帮助。

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

请注意,在第三行,代码检查“<”前一个值但“>” 2。

正如罗斯史密斯二世指出的那样,在 WHEN 之外使用 COUNT将不允许我在 WHEN 中使用“<”之类的操作数。

对于前两个和最后一个 WHEN,不需要比较符号,所以嘿,我现在可以计算 6 个而不是 10 个,所以每个 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 个匹配记录,第三行将是 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  
4

1 回答 1

0

第一的,

REGEXP 'cats|dogs|birds|rats|horses|cows'

将匹配brats以及rats. 你可能想要:

IN ('cats','dogs','birds','rats','horses','cows')

也许

REGEXP '^(cats|dogs|birds|rats|horses|cows)$' 

其次,如果您替换CASE WHEN xCASE x WHEN,那将简化一些事情。

最后,我会将最后的 JOIN 子句移到 WHERE,因为它并没有真正加入表。

这是重写的查询:

SELECT
    U.id,
    COUNT(C.assets_animal_name IN ('cats','dogs','birds','rats','horses','cows')) AS leMatchesCount,
    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 4 THEN 1.11
            WHEN 3 THEN 1.11
            WHEN 2 THEN 1.11
            WHEN 1 THEN 0.55
        END)
    , 0) AS leRank1,
    IF(MATCH(C.assets_animal_name) AGAINST ("any animal" IN BOOLEAN MODE), 1.11,
    COALESCE(
        (CASE COUNT(C.assets_animal_name IN ('cats','dogs','birds','rats','horses','cows'))
            WHEN 6 THEN 1.11
            WHEN 5 THEN 0.88 
            WHEN 4 THEN 0.37
            WHEN 3 THEN 0.37
            WHEN 2 THEN 0.37
            WHEN 1 THEN 0.18
            END)
    , 0)) AS leRank2
FROM
    us3r U
LEFT OUTER JOIN 
    assets_animals C ON
        C.user_id = U.id
WHERE           
    C.assets_animal_name IN ('cats','dogs','birds','rats','horses','cows')
GROUP BY
    U.id

让我们知道这是否有助于提高性能。

于 2012-10-15T02:21:14.363 回答