子查询的优化

时间:2017-06-29 08:41:38

标签: mysql sql

我有用户和群组之间的关系。用户可以在一个组中,也可以不在组中。

编辑:在模型中添加了一些内容以使其更方便。

enter image description here

假设我有一个规则是在一个组中添加用户,考虑到它有一个特定的城镇,以及一个自定义元数据,如年龄18)。

当然,我这样做是为了知道我必须在18岁的巴黎人群中添加哪些用户:

        SELECT user.id AS 'id'
        FROM user
        LEFT JOIN
        (
            SELECT user_id 
            FROM user_has_role_group 
            WHERE role_group_id = 1 -- Group for Paris
        )
        AS T1
        ON user.id = T1.user_id
        WHERE 
        (
        user.town = 'Paris' AND JSON_EXTRACT('custom_metadata', '$.age') = 18
        )
        AND T1.user_id IS NULL

它适用于&为我提供了要在组中插入的用户的ID。

但是,当我有50个小组继续进行时,比如50个小镇或不同年龄段,它迫使我做50个请求,这对我的数据库来说非常缓慢且效率不高。

我如何为每个组生成结果?

类似的东西:

role_group_id          user_to_add
1                 1
1                 2
2                 1
2                 3

我现在知道这样做的唯一方法就是在上面的几个子查询中做一个UNION,但当然它很慢。

请注意,custom_metadata字段是用户定义的字段。我无法创建特定的列或表。

非常感谢你的帮助。

2 个答案:

答案 0 :(得分:1)

如果我很了解你:

select user.id, grp.id
from user, role_group grp
where  (user.id, grp.id) not in (select user_id, role_group_id from user_has_role_group) and user.town in ('Paris', 'Warsav')

该代码列出了不属于其中一个城镇的用户和组列表。

答案 1 :(得分:0)

要将缺少的条目添加到user_has_role_group,您可能希望在这些城镇名称及其group_id之间建立一些映射。

以下示例仅使用带有联合的子查询。
但是你可以用表格中的选择来代替它 甚至可能来自role_group,如果这些名称与用户城镇名称相关联。

insert into user_has_role_group (user_id, group_id)
select u.user_id, g.group_id
from user u
join (
  select 'Paris' as name, 1 as group_id union all
  select 'Rome', 2
  -- add more towns here
) g on (u.town = g.name)
left join user_has_role_group ug 
  on (ug.user_id = u.user_id and ug.role_group_id = g.group_id)
where u.town in ('Paris','Rome') -- add more towns here
  and json_extract(u.custom_metadata, '$.age') = 18
  and ug.id is null;