Как заставить этот запрос работать быстрее? - PullRequest
0 голосов
/ 22 ноября 2011

У меня такой запрос:

    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 

Первое, что я хочу сформировать в этом запросе, это дать мне 10 последних строк формы om_chapter, сгруппировав manganame и упорядочив по идентификатору. ...

В простом запросе с группой или отличным результатом будет такой:

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` )

И я использую sub select в where, потому что хочу, чтобы поле Active в таблице om_manga было 1 ..

Для сброса суб-выбора я на самом деле не пытался присоединиться, но я буду ..!

Ответы [ 4 ]

1 голос
/ 22 ноября 2011

Я бы ввел внешний ключ contstrain в таблицу 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
1 голос
/ 22 ноября 2011

Возможно, я неправильно понял ваши намерения. Но вот одна попытка:

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
0 голосов
/ 22 ноября 2011

Используйте левое внешнее соединение (и потеряйте подзапросы и обратные кавычки):

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'.

0 голосов
/ 22 ноября 2011

Почему бы не простое соединение?

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

, если я не читаю вашу версию.

...