Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/61.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
MySQL交叉点_Mysql_Sql_Select_Intersection - Fatal编程技术网

MySQL交叉点

MySQL交叉点,mysql,sql,select,intersection,Mysql,Sql,Select,Intersection,我有一个现有的网站,其数据库设计不正确,并包含大量的记录,所以我们不能改变数据库结构 本期数据库主要包括4个表、用户、问题、选项和答案。有一组标准的问题和选项,但对于每个用户,答案表中的每一组问题和选项都有一行。数据库结构和示例数据可访问 现在,作为高级搜索的新要求,我需要通过应用多个搜索过滤器来查找用户。有关的注释中给出了示例输入和预期输出 我尝试应用所有类型的连接,但总是以某种方式失败。有人能帮我写正确的查询吗?最好是轻量级/优化的连接,因为数据库包含大量记录(10000多个用户、100多个

我有一个现有的网站,其数据库设计不正确,并包含大量的记录,所以我们不能改变数据库结构

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

现在,作为高级搜索的新要求,我需要通过应用多个搜索过滤器来查找用户。有关的注释中给出了示例输入和预期输出

我尝试应用所有类型的连接,但总是以某种方式失败。有人能帮我写正确的查询吗?最好是轻量级/优化的连接,因为数据库包含大量记录(10000多个用户、100多个问题、500多个选项和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;
请注意:在real数据库中,
答案
表的
用户id
问题id
选项id
列被索引

正在运行上给出的查询

为了诺思的回答


对于calcinai的答案。

将所有您的n过滤器添加到WHERE using OR中,并在have(SUM(CASE))中重复使用and:

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语法。

这需要对动态筛选器进行一些修改,但您真正想要做的是按ID进行搜索,因为这将意味着更少的联接和更快的查询

这将产生您期望的结果。我假设搜索过滤器是根据数据库中的选项生成的,因此,与其将实际值传递回查询,不如传递ID

多个内部联接用于支持多个AND条件并自动减少结果集

SELECT * FROM users u
INNER JOIN answers a ON a.user_id = u.id
  AND (a.question_id, a.option_id) IN ((1,3),(1,5)) # q 1: Lang, answer 3/5: En/Ru
INNER JOIN answers a2 ON a2.user_id = u.id
  AND (a2.question_id, a2.option_id) = (2,8) # q 2: Height, answer 8: 1.71...
GROUP BY u.id;
我建议确保(用户id、问题id、选项id)上有用于搜索的索引:

ALTER TABLE `answers` ADD INDEX idx_search(`user_id`, `question_id`, `option_id`);

否则,它应该为联接使用主键(如果定义正确的话),这样会很快。

感谢您的回答@CANCINAI+1,是的,所有FK列都被索引,我传递的是ID,而不是值。在小提琴上,我试图把一个复杂的问题简化。有一个问题,你说的“我”是什么意思?那是个打字错误。我那愚蠢的电脑自动把“u”改成“i”!Gt8。谢谢。它正在制作一个简单的小提琴示例。让我试试看。如果有什么问题,我会回来的。再次感谢。感谢@dnoeth,+1的工作查询。我必须承认,到目前为止,我不明白你在
拥有
之后写了什么。我必须看一下文件。我将应用您的和@CANCINAI andwer,并将接受更优化的。再次感谢您的回答,更重要的是,这对我来说是一件新事情(SUM/CASE-WHEN等)@Kapil-Sharma:当然我的版本更有效:-)添加附加条件很容易,添加一个新条件到WHERE/have,而不是另一个join。关于逻辑:至少一次检查每个条件的计算结果是否为真,因为在实时情况下,可能会有30-50个过滤器,30-50个连接显然会杀死DB服务器,特别是当查询发生得太频繁时。我们仍然需要在具有500000多条记录的真实数据库上实现一些基准测试。请给我点时间,可能还要几个小时。我会接受这两个答案,但不要这样。我很想知道你们的基准测试结果。我同意@dnoeth的查询在给定的数据集上可能会更快,但我认为当有相当数量的数据时,它会崩溃。有
内部联接的开销
,但我认为,与创建一个巨大的派生表,然后对一个固有的不可索引列执行
操作相比,它的意义就显得微不足道了。如果表被正确索引,并且每个单独的select将使用基于索引的访问,或者如果行数被快速减少(高选择性),它可能会更快。