mysql groupwise max as second where condition

时间:2015-02-12 16:16:12

标签: mysql sql groupwise-maximum

我有一个看起来非常低效的工作查询;我想知道我是否错过了改进它的简单方法。

简单表:

id  date        master_id
-------------------------
1   2015-02-01  0
2   2015-02-02  0
3   2015-02-03  0
4   2015-02-04  1
5   2015-02-02  1
6   2015-02-17  1
7   2015-02-27  1
8   2015-01-01  1

目标:获取master_id为零的所有行,或者master_id不为零,并且同一master_id的其他行没有更早的日期。按日期订购每个结果。

当前查询,使用groupwise minimum子查询创建第二个WHERE条件。


SELECT *
FROM `test`
WHERE `master_id` =0
OR `id` IN (

    SELECT test.`id`
    FROM (
        SELECT `master_id`, MIN(`date`) AS mindate
        FROM `test`
        WHERE `master_id`  0       
        GROUP BY `master_id`
    ) AS x
    INNER JOIN `test` ON x.`master_id` = test.`master_id`
    AND x.mindate= test.`date`
)
ORDER BY `date`

它可以工作,但是EXPLAIN使它看起来效率低下:

id  select_type         table       type    possible_keys   key         key_len     ref     rows    Extra
-------------------------------------------------------------------------------------------------------------
1   PRIMARY             test        ALL     NULL            NULL        NULL        NULL    8       Using where; Using filesort
2   DEPENDENT SUBQUERY  derived3    system  NULL            NULL        NULL        NULL    1   
2   DEPENDENT SUBQUERY  test        eq_ref  PRIMARY         PRIMARY     4           func    1       Using where
3   DERIVED             test        ALL     NULL            NULL        NULL        NULL    8       Using where; Using temporary; Using filesort

我可以改善吗?我应该把它分成两个查询,一个用于ID = 0,一个用于分组分钟?提前谢谢。

2 个答案:

答案 0 :(得分:0)

避免内部联接可以改善查询:

SELECT *
FROM `test`
WHERE `master_id` =0
OR `id` IN (
    SELECT t1.id 
    FROM (SELECT * 
        FROM test t2 
        WHERE t2.master_id!=0   
        ORDER BY t2.date ASC) t1
    GROUP BY t1.master_id
)
ORDER BY `date`;

答案 1 :(得分:0)

这个怎么样......

SELECT * FROM test WHERE master_id = 0
UNION 
SELECT x.*
  FROM test x
  JOIN (SELECT master_id,MIN(date) min_date FROM test GROUP BY master_id) y
    ON y.master_id = x.master_id 
   AND y.min_date = x.date;