繁体   English   中英

SQL 根据表 B 中的标准返回表 A 的结果

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

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

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

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

我需要编写一个 sql 语句,它只返回通过元数据表中的几个不同分数条件的用户电子邮件。

// 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 分),那么我希望该用户在结果集中,否则我希望该用户被忽略。

我已经尝试使用用户存储的函数/光标,它采用 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 个查询,一个从仅passing用户的user_metadata获取user_ids ,然后再到 SELECT WHERE IN 在该 ID 列表上会更好吗?

尝试使用 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 score > 0
        END) AS total
    FROM user_metadata
    GROUP BY user_id
) AS t ON u.id = t.user_id

您也无需在查询中使用GROUP BY u.id ,因为这是您要查询的表的主键; 希望 MySQL 能优化它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM