MySQL查询优化 - 1个查询vs 2个查询

时间:2015-05-27 08:46:17

标签: mysql optimization

当我们遇到以下问题时,我今天和一位教授发生了争执。假设我们想要建立一个电影测验,每个问题都是一个"从四个答案中选择..."游戏类型。然后,我们根据从数据库中查询的信息构建我们的问题。其中一个问题如下:

Who directed the movie X...?

然后我们将从Movies表中查询数据库,如下所述

Field       Type            Null    Key Default     Extra
id          int(11)         NO      PRI NULL        auto_increment
title       varchar(100)    NO      NULL    
year        int(11)         NO      NULL    
director    varchar(100)    NO      NULL    
banner_url  varchar(200)    YES     NULL    
trailer_url varchar(200)    YES     NULL

现在,我的问题在哪里。在我看来,我相信应该能够一次查询数据库,并限制我们的请求产生4个结果。从这4个答案中,随机选择一个作为正确答案,而其他3个答案是错误答案(注意这将在离线状态下完成)

以下是我提出的问题:

SELECT DISTINCT title, director
FROM movies
ORDER BY RAND()
LIMIT 4;

然而,我的教授认为两个SQL关键字DISTINCTLIMIT不够安全,无法阻止我们获得重复项。更进一步,他提出了一个边缘案例"如果我们的电影桌上只有一个导演怎么办??"因此得出结论,我们必须使用两个查询;第一个得到我们正确的答案,第二个问题得到我们错误的答案。

如果我们可以保证我们的桌子上有多个导演,从而消除了我教授提出的边缘情况,我的查询不会每次产生成功的结果吗?我已经查询了大约10到20次,每个查询产生了我想要的确切结果。因此,我很难找到进一步的证据来挑选1查询的2查询方法。

编辑 - 我相信我的问题可能无法解决问题。这两个答案依赖于我们查询之前已知的电影标题。但是,我们不确定哪部电影会填满这个问题"谁执导了??"我希望在数据库中查询4个随机结果,然后从我们代码的Java端的4个随机结果中选择,以确定"正确"回答,将所述电影的标题插入到问题中,并为问题产生4个可能的答案。

3 个答案:

答案 0 :(得分:0)

我认为您需要这样的查询:

SELECT title, director, CASE WHEN title = :title THEN 1 ELSE 0 END As isAnswer
FROM movies
GROUP BY title, director
ORDER BY 
    CASE WHEN title = :title THEN 0 ELSE 1 END,
    RAND()
LIMIT 4;

请记住,第一行就是答案。

答案 1 :(得分:0)

我相信你的教授在这方面是部分正确的...你的查询本身可能巧合,但这可能是基于一小部分电影并且正在将电影放入其结果集中。所以,举个例子,你有1000部电影和47部导演,你选择的一部电影“X”,导演只列出了1000部电影中的3部......导演的结果集是多么逼真你有那个导演......

Sha的回答非常接近,因为它保证了4个结果,但将电影“X”的导演浮动到顶部,但该版本有额外的东西不适用。你只需要导演的名字,而不是他们所做的电影。然后你可以通过rand()命令结果,以确保最终的顺序是随机的。

select
      pq.*
   from
      ( select 
              m.director,
              max( case when m.title = cTitleOfMovieYouWant then 1 else 0 end ) 
                 as FinalAnswer
           from 
              movies m
           group by
              m.director
           order by 
              max( case when m.title = cTitleOfMovieYouWant then 1 else 0 end ) DESC,
              RAND()
           limit
              4 ) pq
   order by 
      RAND()

所以,内部查询只关心一个导演,如果他们是有关电影的导演或者不是导演的话。 MAX(情况/时间)很重要,因为如果导演“乔”指导了5部电影,其中只有一部是所需的电影。你不希望乔出现一次作为有效的导演,而不是曾经不是导演。因此,对于1部电影,该标志将设置为1,所有其他不是“X”的电影将具有0的标志,因此我们希望将导演的整体标志保持为1。

现在,由于给定电影只有一个导演,同一个MAX(情况/时间)的顺序是DESCENDING顺序,它会强制这个导演到列表顶部,然后随机播放所有其他导演。 / p>

一旦返回4条记录的结果,外部查询就会运行它并通过RAND()命令IT,从而改变最终的顺序。

答案 2 :(得分:0)

它变得混乱,因为一位导演可能指导多个头衔。

尝试以下两个步骤:

SELECT @correct := director FROM movies WHERE title = :title; -- first get corret answer

( SELECT DISTINCT director
    FROM movies
    WHERE director != @correct
    ORDER BY RAND()  LIMIT 3 )   -- 3 other directors
UNION ALL
( SELECT @correct )             -- and the correct answer
ORDER BY RAND();      -- shuffle the 4 answers

在大子查询中:

  1. WHERE完全在......之前完成。
  2. DISTINCT发生在...之前......
  3. ORDER BY发生在...之前......
  4. LIMIT