mysql 这个带有重复的WHERE子句的查询可以优化吗?

7cjasjjr  于 2023-11-16  发布在  Mysql
关注(0)|答案(3)|浏览(132)

我有一个查询,它为给定的分支选择用户。

SELECT u.first, u.last, u.id, 
    (SELECT u1.user_type
    FROM users_branches AS u1
    WHERE u.id = u1.user_id AND u1.branch_id = @foo
    LIMIT 1)
FROM users AS u
WHERE EXISTS
    (SELECT 1
    FROM users_branches AS u0
    WHERE u.id = u0.user_id AND u0.branch_id = @foo)

字符串
这里是EF Core LINQ查询,它生成了这个SQL。

int branchId = 123;
var users = await Users
    .Where(x => x.UsersBranches.Any(ub => ub.BranchId == branchId))
    .Select(user => new
    {
        UserId = user.Id,
        FirstName = user.First,
        LastName = user.Last,
        UserType = user.UsersBranches.FirstOrDefault(x => x.BranchId == branchId).UserType
    }).ToListAsync();


我不喜欢WHERE子句需要被复制,只是说“只给我有users_branches记录的用户,并返回该记录中的一些数据”。有没有更有效的方法来做到这一点?我可以想象一个使用GROUP BY的解决方案,但我不确定这是否真的会更好。

vltsax25

vltsax251#

一种方法是使用joins

SELECT u.id AS UserId, u.first AS FirstName, u.last AS LastName 
FROM users u
INNER JOIN users_branches ub ON u.id = ub.user_id
WHERE ub.branch_id = 123

字符串
另一种方法是使用subquery

SELECT u.id AS UserId, u.first AS FirstName, u.last AS LastName
FROM users u 
WHERE u.id IN (
  SELECT user_id 
  FROM users_branches 
  WHERE branch_id = 123
)


如果你看到主要的区别是联接版本在一个语句中查询两个表,而子查询版本在查询用户之前首先在子查询中过滤UsersBranches。

注意:连接通常效率更高,因为它允许数据库同时访问两个表并优化查询计划。子查询可能会导致性能降低,因为它将查询分为两部分。

--希望这对你有帮助。

f3temu5u

f3temu5u2#

我觉得这个版本更容易阅读:

SELECT users.first, users.last, users.id, MIN(users_branches.user_type)
FROM users
INNER JOIN users_branches ON
    users.id = users_branches.user_id
    AND users_branches.branch_id = @foo
GROUP BY users.id

字符串
至于它是否提供更好的性能,这将取决于许多因素,如索引等。我建议运行一些测试,并检查EXPLAIN SELECT ....的输出,以了解您尝试的不同查询

wd2eg0qa

wd2eg0qa3#

也许你可以试试这样的

SELECT u.first, u.last, u.id, u0.user_type
FROM users u
JOIN users_branches u0 ON u.id = u0.user_id AND u0.branch_id = @foo
WHERE NOT EXISTS (
    SELECT 1
    FROM users_branches u1
    WHERE u1.user_id = u0.user_id
    AND u1.branch_id = u0.branch_id
    AND u1.id < u0.id
)

字符串

相关问题