【问题标题】:How to make this query run faster?如何使这个查询运行得更快?
【发布时间】:2011-11-22 18:58:23
【问题描述】:

我有这样的查询:

    SELECT 
    `om_chapter`.`manganame` as `link`,
    (SELECT `manganame` FROM `om_manga` WHERE `Active` = '1' AND `om_manga`.`link` = `om_chapter`.`manganame` LIMIT 0,1) AS `manganame`,
    (SELECT `cover` FROM `om_manga` WHERE `Active` = '1' AND `om_manga`.`link` = `om_chapter`.`manganame` LIMIT 0,1) AS `cover`,
    (SELECT `othername` FROM `om_manga` WHERE `Active` = '1' AND `om_manga`.`link` = `om_chapter`.`manganame` LIMIT 0,1) AS `othername`
FROM `om_chapter`
WHERE 
    `Active` = '1' AND 
    (SELECT `Active` From `om_manga` WHERE `om_manga`.`link` = `om_chapter`.`manganame` LIMIT 0,1) AND 
    `id` IN ( SELECT MAX(`id`) FROM `om_chapter` WHERE `Active` = '1' GROUP BY `manganame` )
ORDER BY `id` DESC LIMIT 10

那么我怎样才能使这个查询更快呢?

这是我的桌子:

om_chapter:

id  | manganame     | chapter   | Active
-----------------------------------------
1   | naruto        | 1         | 1
2   | naruto        | 12        | 1
3   | naruto        | 22        | 1
4   | bleach        | 10        | 1
5   | bleach        | 15        | 1
6   | gents         | 1         | 1
7   | naruto        | 21        | 1

om_manga:

id  | othername | manganame     | cover     | Active
-----------------------------------------------------
1   | naruto    | naruto        | n.jpg     | 1
2   | bleach    | bleach        | b.jpg     | 1
4   | gents     | gents         | g.jpg     | 1 

我想要形成这个查询的第一件事是通过将 manganame 分组并按 id 排序给我 om_chapter 的最后 10 行。我尝试通过使用 group 甚至 distinct 来使用简单的查询,但它们都没有给我正确的结果...

在使用 group 或 distinct 的简单查询中,结果如下:

id  | manganame     | chapter   | Active
-----------------------------------------
7   | prince        | 21        | 1
5   | gent          | 15        | 1
2   | naruto        | 12        | 1
1   | bleach        | 1         | 1

但我想要这个结果:

id  | manganame     | chapter   | Active
-----------------------------------------
9   | gents         | 21        | 1
8   | bleach        | 21        | 1
7   | prince        | 21        | 1
6   | naruto        | 1         | 1

所以我用这个:

WHERE 
`Active` = '1' AND 
(SELECT `Active` From `om_manga` WHERE `om_manga`.`link` = `om_chapter`.`manganame` LIMIT 0,1) AND 
`id` IN ( SELECT MAX(`id`) FROM `om_chapter` WHERE `Active` = '1' GROUP BY `manganame` )

我在 where 中使用子选择,因为我希望 om_manga 表中的 Active 字段为 1..

对于sub select的reset,其实我并没有尝试join,但是我会..!

【问题讨论】:

  • 发布有关表结构的其他信息会有所帮助。像索引等。
  • 哇。这比它需要的复杂了大约八十倍。我没有时间尝试弄清楚您要完成的工作,但是您应该查看 JOIN 语句(我认为您需要为此使用 INNER JOIN ......)。基本上,它将两个表连接在一起,您可以设置连接条件。我认为它在大多数情况下比子查询要快。
  • @kamal 这个查询几乎肯定比实际需要的要复杂,但是如果不知道您要达到什么目的,就很难提供更好的解决方案。这个查询应该产生什么输出?具体来说,您是在寻找每部漫画的每一章的结果,还是只寻找编号最高的章节?
  • @danielrsmith 我在第一篇文章中解释了一点
  • @djacobson 我想要 om_chapter 的最后 10 行,方法是对 manganame 进行分组(我在第一篇文章中解释过),并在两个表中按相等的 manganame 选择 om_manga 的一行...

标签: mysql select summary


【解决方案1】:

我可能误解了你的意图。但这里有一个尝试:

SELECT c.`manganame` AS `link`
     , m.`manganame`
     , m.`cover`
     , m.`othername`
FROM 
     `om_manga` m 
     INNER JOIN `om_chapter` c 
     ON m.`link` = c.`manganame`
     INNER JOIN 
     ( SELECT `manganame`, MAX(`id`) AS `maxid` 
       FROM `om_chapter` 
       WHERE `Active` = '1' 
       GROUP BY `manganame` ) mx
     ON mx.`maxid` = c.`id`
ORDER BY c.`id` DESC LIMIT 10

【讨论】:

    【解决方案2】:

    我将在 om_chapter 表中引入一个外键约束,以说明从漫画到相应章节的链接。

    这就是我将问题概念化的方式。

    A manga can have many chapters.  A chapter belongs to one manga. 
    

    然后我会修改 om_chapter 表,包括一个外键,用于链接到漫画的章节。

    ALTER TABLE om_Chapter (
    ADD mangaID int references om_Manga (id)
    )
    

    并删除 manganame 列,因为它现在只是多余的

     ALTER TABLE om_Chapter (
     DROP COLUMN manganame
    )
    

    你的表格可能看起来像这样。

    om_manga:

    id  | othername | manganame     | cover     | Active
    -----------------------------------------------------
    1   | naruto    | naruto        | n.jpg     | 1
    2   | bleach    | bleach        | b.jpg     | 1
    4   | gents     | gents         | g.jpg     | 1 
    

    om_chapter:

    id  | chapter   | Active  | mangaID
    -----------------------------------------
    1   | 1         | 1       |  1
    2   | 12        | 1       |  1
    3   | 22        | 1       |  1
    4   | 10        | 1       |  2
    5   | 15        | 1       |  2
    6   | 1         | 1       |  4
    

    终于可以像这样查询表了

    SELECT TOP 10 m.Manganame as link,
      m.Manganame,
      m.cover,
      m.othername,
    
    FROM om_manga as m INNER JOIN
      om_chapter as c ON m.ID = c.mangaID
    
    WHERE m.active = 1 AND c.active = 1
    ORDER BY m.ID DESC
    

    【讨论】:

    • 其实我心里有这个想法……我后来试了!并感谢您的回答!
    【解决方案3】:

    为什么不简单的加入?

    SELECT om_chapter.manganame, cover, othername
    FROM om_chapter
    JOIN om_manga ON om_chapter.manganame = om_manga=manganame
    WHERE om_chapter.Active = 1 AND om_manga.Active = 1
    

    除非我误读了你的版本。

    【讨论】:

    • 看起来他希望每部漫画都有一条记录(参见章节表上的 MAX(id)...)
    【解决方案4】:

    使用左外连接(并丢失子查询和反引号):

    SELECT c.manganame AS link,
           m.manganame AS manganame,
           m.cover     AS cover,
           m.othername AS `othername
      FROM om_chapter    AS c
      LEFT JOIN om_manga AS m
        ON c.manganame = m.manganame
     WHERE c.Active = '1'
       AND c.id IN (SELECT MAX(o.id)
                      FROM om_chapter AS o
                     WHERE o.active = 1
                     GROUP BY o.manganame)
     ORDER BY c.id DESC LIMIT 10
    

    如果是我的查询,我可能也会选择“c.id AS id”。

    【讨论】:

      猜你喜欢
      • 2014-11-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-25
      • 1970-01-01
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多