SQL return 结果 Table A,基于 Table B 的标准

SQL return results for Table A, based on criteria from Table B

我有 2 个 table 共享一对多关系。假设以下结构:

users             users_metadata
-------------     -------------
id | email        id | user_id | type | score

一个用户可以有很多元数据。用户 table 有 100k 行,users_metadata table 有 300k 行。它可能会增长 10 倍,所以无论我写什么都需要针对大量数据进行优化。

我需要写一个 sql 声明 returns 只有通过元数据 table 中发现的几个不同评分条件的用户电子邮件。

// if type = 1 and if score > 75 then <1 point> else <0 points>
// if type = 2 and if score > 100 then <1 point> else <0 points>
// if type = 3 and if score > 0 then [-10 points] else <0 points>

// there are other types that we want to ignore in the score calculations

如果用户超过阈值(例如 >= 1 分),那么我希望该用户出现在结果集中,否则我希望忽略该用户。

我已经尝试用户存储 function/cursor 接受 user_id 并循环遍历元数据以找出要点,但结果执行速度非常慢(尽管它确实有效)。

目前我有这个,执行大约需要 1 到 3 秒。

SELECT u.id, u.email,

    (
        SELECT 
            SUM(
                IF(k.type = 1, IF(k.score > 75, 1, 0), 0) + 
                IF(k.type = 2, IF(k.score > 100, 1, 0), 0) +
                IF(k.type = 3, IF(k.score > 0, 1, -10), 0)
            ) 
        FROM user_metadata k WHERE k.user_id = u.id
        
    ) AS total

FROM users u GROUP BY u.id HAVING total IS NOT NULL;

我觉得在 10 倍时这会更慢。 1 到 3 秒的查询执行时间对于我已经需要的来说太慢了。

更理想的方法是什么?

如果我也为此使用 PHP 之类的语言,那么 运行 2 个查询,其中一个从 user_metadata 中获取 user_ids,只有 passing用户,然后再 SELECT 在该 ID 列表中的 WHERE IN 更好?

尝试使用 JOIN 而不是相关子查询。

SELECT u.id, u.email, t.total
FROM users AS u
JOIN (
    SELECT user_id, SUM(CASE type
        WHEN 1 THEN score > 75
        WHEN 2 THEN score > 100
        WHEN 3 THEN IF(k.score > 0, 1, -10)
        END) AS total
    FROM user_metadata
    GROUP BY user_id
    HAVING total >= 1
) AS t ON u.id = t.user_id

在子查询中进行分组和过滤使连接更小,这可以显着提高性能。

您也不需要在查询中使用 GROUP BY u.id,因为那是您正在查询的 table 的主键;希望 MySQL 会优化它。