mysql 子查询-记录不是有序形式

92dk7w1h  于 2023-06-28  发布在  Mysql
关注(0)|答案(4)|浏览(80)

我有三张table:

user: id, name
keyword: id, name
userkeyword: id, user_id, keyword_id

我想用以下方式执行查询:
显示关键字与登录用户的关键字匹配的用户。按照匹配的关键字的最大数量的顺序,用户应该首先显示
例如:如果用户A有4个匹配的关键字,用户B有8个,用户C有1个,用户D有6个,那么结果应该是,

userB
userD
userA
userC

为此,我使用这个查询(假设登录用户的id为1):

select * 
from user 
where id IN (
    select user_id 
    from userkeywords 
    where keyword_id IN (
        select keyword_id 
        from userkeywords 
        where user_id=1) 
    group by user_id 
    order by count(keyword_id) desc) 
    AND id != 1

这里的结果是越来越完美,但顺序是不正确的。我以以下方式合并了两个查询”

select * 
 from user 
 where id IN (?) 
      AND id!=1
select user_id
 from userkeywords 
 where keyword_id IN (
      select keyword_id 
      from userkeywords 
      where user_id=1) 
 group by user_id 
 order by count(keyword_id) desc

第二个查询以正确的顺序返回user_id,但当我合并两个查询时,顺序发生了变化(错误)。
希望我已经提到了我的查询适当与足够的细节。

tzdcorbm

tzdcorbm1#

子查询返回一个无序集,所以子查询中的order by只对它的limit子句有影响(如果有的话)。除了MySQL以外的任何数据库都会对纯粹的装饰性排序顺序给予错误消息。
没有办法对只存在于where子句中的列进行排序。你得重写查询。一种选择是将in条件替换为joins

select  uk2.name
from    userkeywords uk1
join    userkeywords uk2
on      uk1.keyword_id = uk2.keyword_id
        and uk1.user_id <> uk2.user_id
join    user u2
on      u2.id = uk2.user_id
where   uk1.user_id = 1
group by
        uk2.name
order by
        count(*) desc
3okqufwl

3okqufwl2#

这个应该够了

select uk.user_id, u.name
from userkeywords uk
left join user u on u.id = uk.user_id
where uk.keyword_id IN ( 
    select keyword_id 
    from userkeywords 
    where user_id=1) 
group by uk.user_id 
order by count(uk.keyword_id) desc) AND uk.user_id != 1

此外,JOIN提供了更好的性能。

deikduxw

deikduxw3#

我将使用内部连接来选择正确的行:

SELECT *
FROM user
INNER JOIN (
   SELECT * FROM userkeyword 
   WHERE keyword_id IN (
       SELECT keyword_id 
       FROM userkeyword 
       WHERE user_id=1
   )
) uk 
ON user.id = uk.user_id 
GROUP BY u.id
ORDER BY count(*) DESC;
e4yzc0pl

e4yzc0pl4#

您可以连接这些表并使用GROUP BY计算每个用户匹配的关键字的数量。然后,您可以按计数降序排序,以首先获得具有最大关键字匹配数的用户。你不需要使用子查询。看一看:

SELECT u.id, u.name, COUNT(*) as matched_keywords
FROM user AS u
JOIN userkeyword AS uk1 ON u.id = uk1.user_id
JOIN userkeyword AS uk2 ON uk1.keyword_id = uk2.keyword_id
WHERE uk2.user_id = 1
      AND u.id != 1
GROUP BY u.id, u.name
ORDER BY matched_keywords DESC;

相关问题