通过加入MySQl来优化组

时间:2014-09-29 20:55:31

标签: mysql join

以下是大约76秒的查询。

有没有办法对此进行优化?

仅供参考我已将id和日期字段编入索引。

对不起,我应该解释一下:

  • 我有一堆id,日期和条件(= 1或0)。

  • 我收集条件为1的ID和日期,结果如此 组说,然后查询Group1以选择最小日期。

  • 然后,此最小日期用于将Group1中的帐户标记为1(如果是) 日期大于最短日期。

我希望这会有所帮助。我为第一次简洁而道歉。

SELECT
  o.id,
  o.date,
  IF(o.date > m.min_date,1,0) b
FROM tab o
  JOIN (SELECT DISTINCT
      (id),
      MIN(DATE)    min_date
    FROM tab
    WHERE cond = 1
    GROUP BY id) m
    USING (id)
WHERE o.id = m.id
ORDER BY o.id,o.date

2 个答案:

答案 0 :(得分:2)

您的原始查询并没有在表格中名为id的任何字段上使用唯一键,这是一种奇怪的做法,看起来您似乎在追求以下内容:

    SELECT o.id,                        
           o.date,
           m.date IS NULL b
      FROM tab o
 LEFT JOIN (
        SELECT account_id, MIN(date) min_date
          FROM tab
         WHERE cond=1
      GROUP BY account_id
           ) m
        ON m.account_id = o.account_id
       AND m.min_date = o.date
  ORDER BY o.id, o.date

这应该很快。对于内部分组(account_id, date),您可以在SELECT上使用复合索引。

以下是您不知道的一些提示:

  • DISTINCT对所有选定的列进行操作,DISTINCT(id), MIN(date) min_date将为您提供id和min_date的所有不同组合,ID本身可能会重复,并且其周围的括号为无意义的。也无法将DISTINCT的行为更改为仅处理所选列的子集。
  • SELECT id, MIN(date) ... GROUP BY account_id不会始终返回与account_id组中的最小日期对应的ID。返回的id可以是组中任何未确定的ID。您需要JOIN行到最小日期或使用其他方法来查找相应的ID。

您接受的Mazster答案有一个奇怪的GROUP BY和不必要的IF条款。我已经在下面重写了它,以防这对你有所帮助,但如果它比我上面更新的那个更快,因为它运行每行的子查询,我感到很惊讶。您最好检查每个EXPLAIN计划,因为我相信您可以使用上述查询更快地获得它:

  SELECT o.id,
         o.date,
         o.date > (
     SELECT MIN(DATE) min_date
       FROM tab m
      WHERE m.cond = 1 
        AND m.id = o.id
        AND m.account_id = o.account_id
         ) b
    FROM tab o
ORDER BY o.id,o.date

答案 1 :(得分:1)

我可以看到有自我加入,如何摆脱它?例如:

SELECT
    o.id,
    o.date,
    IF(
        (SELECT 
            MIN(DATE) min_date
            FROM tab m
            WHERE cond = 1 AND o.id = m.id
            GROUP BY account_id
        ) < o.date,1,0
    ) b
FROM tab o
ORDER BY o.id,o.date