[英]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.