datetime =没有全表扫描的日期?

时间:2013-07-29 03:20:01

标签: mysql sql

可能重复:How to select date from datetime column?

但接受答案的问题是它会执行全表扫描。

我想做这样的事情:

UPDATE records SET earnings=(SELECT SUM(rate) 
FROM leads 
WHERE records.user_id=leads.user_id 
   AND DATE(leads.datetime)=records.date)

注意最后一部分:DATE(leads.datetime)=records.date。这正是它需要做的事情,但它必须扫描每一行。有些用户有数千个潜在客户,因此可能需要一段时间。

leads表格INDEX上有user_iddatetime

我知道您可以使用区间函数并执行类似WHERE datetime BETWEEN date AND interval + days之类的操作。

最有效和最准确的方法是什么?

2 个答案:

答案 0 :(得分:3)

我不熟悉MySQL中的日期函数,但尝试将其更改为

UPDATE records SET earnings=
  (SELECT SUM(rate) 
   FROM leads 
   WHERE records.user_id=leads.user_id 
     AND  leads.datetime >= records.date
     And  leads.datetime < records.date [+ one day])  -- however you do that in MySQL

您正在进行完整的表扫描,因为表达式DATE(leads.datetime)不是Sargable。这是因为它是一个函数,它需要对存储在表的列中的值进行操作,并且还存储在该列的任何索引中。显然,函数的值不能预先计算并存储在任何索引中,只能存储在实际的列值中,因此在执行函数后,没有索引搜索可以识别哪些行将满足Where子句谓词中表示的条件。更改表达式以使列值在 本身 一侧或另一个where子句运算符(等号或其他)允许列值在要基于单个表达式搜索的索引。

答案 1 :(得分:2)

你可以试试这个:

UPDATE records
    SET earnings = (SELECT SUM(rate)
                    FROM leads
                    WHERE records.user_id=leads.user_id AND
                          leads.datetime >= records.date and
                          leads.datetime < date_add(records.date, interval 1 day)
                   );

您需要leads(user_id, datetime)上的索引才能生效。