mysql - 如何使用 IN 数组过滤器连接三个表,但仍获取第三个表中的所有行

标签 mysql sql select join

我有通过 UserSkills 表连接的用户和技能表,以实现多对多关系。以下是表中的内容:

Users (id, username)
Skills (id, name)
UserSkills (user_id, skill_id)

我拥有一系列正在寻找的技能 ['C#'、'SQL']。因此,我正在执行加入 IN 过滤操作,以仅获取我需要的用户。

SELECT (username, GROUP_CONCAT(Skills.name)) FROM Users
JOIN UserSkills ON Users.id = UserSkills.user_id
JOIN Skills ON Skills.id = UserSkills.skill_id AND Skills.name IN ('C#', 'SQL')
GROUP BY Users.id

我想要获得相同的用户列表,但具有他们所有的技能,而不仅仅是我正在寻找的那些。例如:

In my case I get: username: 'joe' | skills: 'C#', 'SQL'
I want to get: username: 'joe' | skills : 'C#', 'SQL', 'JavaScript', 'NodeJS'

请帮忙。

最佳答案

最直接的方法是第二次加入:

SELECT u.username, GROUP_CONCAT(DISTINCT userS.name)
FROM Users AS u
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS filterS ON filterS.id = us.skill_id AND filterS.name IN ('C#', 'SQL')
INNER JOIN Skills AS userS ON userS.id = us.skill_id
GROUP BY u.id

但是您将需要 GROUP_CONCAT 中的 DISTINCT,因为过滤技能基本上将与用户技能交叉连接。另外值得注意的是,此查询获取的用户具有任何指定的技能,而不是全部。这是一个更好的解决方案:

SELECT u.username, GROUP_CONCAT(s.name) AS skils
   , COUNT(CASE WHEN s.name IN ('C#', 'SQL') THEN 1 ELSE NULL END) AS matchedSkillCount
FROM Users AS u
   INNER JOIN UserSkills AS us ON u.id = us.user_id
   INNER JOIN Skills AS s ON s.id = us.skill_id
GROUP BY u.id
HAVING matchedSkillCount > 0 -- You can replace 0 with the number of matches you want
;

...但是在非常大的数据库上,上述操作可能会变得昂贵;其他几个选择:

SELECT u.username, GROUP_CONCAT(DISTINCT userS.name)
FROM Skills AS filterS 
INNER JOIN UserSkills AS ufs ON filterS.id = ufs.skill_id
INNER JOIN Users AS u ON ufs.user_id = u.id
INNER JOIN UserSkills AS us ON u.id = us.user_id
INNER JOIN Skills AS userS ON us.skill_id = userS.id
WHERE filterS.name IN ('C#', 'SQL')
GROUP BY u.id;

SELECT u.username, GROUP_CONCAT(s.name) AS skils       
FROM Users AS u
   INNER JOIN UserSkills AS us ON u.id = us.user_id
   INNER JOIN Skills AS sON s.id = us.skill_id
WHERE u.id IN (
   SELECT DISTINCT ufs.user_id
   FROM Skills AS filterS 
      INNER JOIN UserSkills AS ufs ON filterS.id = ufs.skill_id
   WHERE filterS.name IN ('C#', 'SQL')
)
GROUP BY u.id
;

逻辑上,WHERE 在连接之后应用;但大多数 RDBMS(如 MySQL)通过使用 WHERE 条件来最小化连接在一起的行来优化执行。

关于mysql - 如何使用 IN 数组过滤器连接三个表,但仍获取第三个表中的所有行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48548879/

相关文章:

mysql - 在c中调用MySQL存储过程,传递变量参数

mysql - 如何在同一查询中获取返回行数和数据的 count()

sql - SSIS : how to run stored procedure in Data Flow Task

JQuery - 获取选择值

php - 从 php 生成 xml 和 xsl

mysql - 如何使用 mysql 编写查询,与使用子查询的多个值相比,我可以获得一些值

php - Laravel artisan 忽略我的 app/config/database.php

javascript - 改变 richselect 的输入颜色

php - 选择特定的重复数据库值并显示计数

mysql - 崩溃后启动 MySQL 时出错