查询的一部分是:
SELECT * FROM `o` WHERE ....
AND `id` IN (SELECT DISTINCT `id` FROM `o` WHERE `activity` = '1' AND `date` < '20130310' ORDER BY `id` ASC)
AND `id` NOT IN (SELECT DISTINCT `id` FROM `o` WHERE `activity` = '1' AND `date` BETWEEN '20130310' AND '20130329' ORDER BY `id` ASC)
....
说明:在 20130310 之前有活动且在20130310和20130329之间没有活动的ID
1)我可以加速这个mysql查询吗?
2)帮助ORDER BY
帮助提高IN
和NOT IN
的速度吗?
答案 0 :(得分:2)
由于IN()子查询在MySQL中通常很慢(至少在5.6之前),你最好使用join
SELECT * FROM `o`
LEFT JOIN
(SELECT `id` AS `idactive` FROM `o` WHERE `activity` = '1' AND `date` BETWEEN '20130310' AND '20130329') as t
USING `id`
WHERE `activity` = '1' AND `date` < '20130310' AND `idactive` IS NULL
答案 1 :(得分:0)
你可以这样做
SELECT * FROM `o` WHERE ....
AND `id` IN (SELECT DISTINCT `id` FROM `o`
WHERE `activity` = '1' AND `date` < '20130310'
ORDER BY `id` ASC)
你不需要第二个AND因为你已选择date < 20130310
所以它不会选择20130311
20130312
... 20130329
或您只需执行此查询
即可 SELECT * FROM `o` WHERE ....
AND `activity` = '1' AND `date` < '20130310'
GROUP BY `id`
ORDER BY `id` ASC
答案 2 :(得分:0)
如果id
是您的主键(应该是),那么您的两个与日期相关的子句中的一个是无用的(`date` < '20130310'
总是暗示NOT (`date` BETWEEN '20130310' AND '20130329')
,这样可以简化事情到:
select *
from o
where activity = 1
and date < '20130310'
如果id
实际上是其他字段中的一个(对于名称而言,这是一个非常令人困惑的选择,在这种情况下)是以1-n或nm关系引用单独的表,我假设你'重新寻找ids,其中至少有一个在日期范围内有活动,但之后没有新的活动。在这种情况下,您的查询可以简化为:
SELECT * FROM `o` WHERE ....
AND `id` IN (SELECT `id` FROM `o` WHERE `activity` = '1' AND `date` < '20130310')
AND `id` NOT IN (SELECT `id` FROM `o` WHERE `activity` = '1' AND `date` BETWEEN '20130310' AND '20130329')
换句话说,distinct
和order by
条款都毫无意义。
在任何一种情况下,如果相关,请注意您的date
字段应为date
类型,而不是varchar
类型。