MySQL 交集

标签 mysql sql select intersection

我有一个现有站点,其数据库设计不正确并且包含大量记录,因此我们无法更改数据库结构。

本期数据库主要包含用户、问题、选项、答案4个表。有一组标准的问题和选项,但对于每个用户,每组问题和选项在答案表中都有一行。数据库结构和示例数据可在 SQL fiddle 获得.

现在作为高级搜索的新需求,我需要通过应用多个搜索过滤器来查找用户。示例输入和预期输出在 SQL Fiddle 的评论中给出。 .

我尝试应用所有类型的连接、交集,但它总是以某种方式失败。有人可以帮我编写正确的查询,最好是轻量级/优化的连接,因为数据库包含大量记录(10000 多个用户、100 多个问题、500 多个选项和 answers 表中的 500000 多个记录)?

编辑:基于两个答案,我使用了以下查询

SELECT u.id, u.first_name, u.last_name
FROM users u
    JOIN answers a ON a.user_id = u.id
WHERE (a.question_id = 1 AND a.option_id IN (3, 5))
    OR (a.question_id = 2 AND a.option_id IN (8))
GROUP BY u.id, u.first_name, u.last_name
HAVING
    SUM(CASE WHEN (a.question_id = 1 AND a.option_id IN (3, 5)) THEN 1 ELSE 0 END) >=1
    AND SUM(CASE WHEN (a.question_id = 2 AND a.option_id IN (8)) THEN 1 ELSE 0 END) >= 1;

请注意:在真实数据库中,answers<的user_idquestion_idoption_id 表被索引。

运行在 SQL Fiddle 上给出的查询.

SQL Fiddle对于 dnoeth 的回答。

SQL Foddle对于 calcinai 的回答。

最佳答案

使用 OR 将所有 n 过滤器添加到 WHERE 中,并使用 AND 在 HAVING(SUM(CASE)) 中重复它们:

SELECT u.id, u.first_name, u.last_name
FROM users u JOIN answers a
  ON a.user_id = u.id
JOIN questions q
  ON a.question_id = q.id
JOIN question_options o
  ON a.option_id = o.id
WHERE (q.question = 'Language known' AND o.OPTION IN ('French','Russian'))
   OR (q.question = 'height' AND o.OPTION = '1.51 - 1.7')
GROUP BY u.id, u.first_name, u.last_name
HAVING
  SUM(CASE WHEN (q.question = 'Language known' AND o.OPTION IN ('French','Russian')) THEN 1 ELSE 0 END) >=1
AND 
  SUM(CASE WHEN (q.question = 'height'         AND o.OPTION = '1.51 - 1.7')          THEN 1 ELSE 0 END) >= 1
;

我将您的联接更改为更具可读性的标准 SQL 语法。

关于MySQL 交集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18842629/

相关文章:

sql - 在 SQL 连接中过滤重复项

mysql - 无法启动 mysqld

javascript - 我可以在前端 Javascript 中运行 SQL 查询吗?

mysql - 为什么连接表时 ORDER BY 结果会改变?

sql - 测试两个日期的间隔是否不参与其他间隔

php SELECT (count) in mysql/pdo WHERE 格式化日期

MySQL,从两个表中选择时插入

mysql - 在 MySQL 中使用 CASE 语句更新多行

mysql - 用百分号替换字符串

Python SQLite3/从表中选择行