mysql - 替代IN()

时间:2014-02-25 00:35:16

标签: mysql

我有一个包含| id | postNumber |列的表格。一个或多个条目属于一个postNumber。我需要为每个postNumber请求最新的条目。

SELECT `dienstbuch`.`id` , `dienstbuch`.`postNumber`
FROM `dienstbuch`
WHERE `dienstbuch`.`id`
IN (
SELECT max( `dienstbuch`.`id` )
FROM dienstbuch
GROUP BY `dienstbuch`.`postNumber`
)
ORDER BY `id` DESC
LIMIT 2000,10

在具有许多条目的表上使用时,查询需要很长时间。

我该如何改进?

2 个答案:

答案 0 :(得分:3)

听起来好像你可以在一个直接查询中请求最大ID

SELECT max( `dienstbuch`.`id` ) maxId, postNumber
FROM dienstbuch
GROUP BY `dienstbuch`.`postNumber`

但是如果要检索多个字段,则需要子查询

SELECT `dienstbuch`.`id` , `dienstbuch`.`postNumber`, dienstbuch.field1, dienstbuch.field2
FROM `dienstbuch`
JOIN
(SELECT max( `dienstbuch`.`id` ) id, postNumber
FROM dienstbuch
GROUP BY `dienstbuch`.`postNumber`
) maxID
on dienstbuch.id=maxID.id and dienstbuch.postNumber=maxID.postNumber
ORDER BY dienstbuch.`id` DESC
LIMIT 2000,10

答案 1 :(得分:2)

为了获得更好的性能,作为IN (subquery)谓词的替代,您可以使用JOIN到内联视图(也就是派生表)。

例如:

SELECT d.id
     , d.postNumber
  FROM dienstbuch d
  JOIN ( SELECT MAX(e.id) AS max_id
           FROM dienstbuch e
          GROUP BY e.postNumber
       ) f
    ON f.max_id = d.id   
 ORDER
    BY d.id DESC
 LIMIT 2000,10

这应该会更好,因为它正在执行内联视图的查询一次,而不是为每一行执行子查询,这就是MySQL如何评估IN (subquery)谓词。

如果我们还需要结果集中表中的其他列,那么这是我们使用的正常模式。对于您的特定查询,您实际上根本不需要子查询。您可以使用此查询获得等效的结果集:

SELECT d.id
     , d.postNumber
  FROM dienstbuch d
 GROUP
    BY d.postNumber
 ORDER
    BY d.id DESC
 LIMIT 2000,10

这很可能表现得更好,因为它避免了实现内联视图和执行JOIN操作的开销。

对于这两个查询,索引... ON dienstbuch (postNumber,id)最有可能提高查询性能。