我有一个现有站点,其数据库设计不正确并且包含大量记录,因此我们无法更改数据库结构。
本期数据库主要包含用户、问题、选项、答案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_id
、question_id
和option_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/