这是比较2表的键时获得最小和最大日期的最佳方法

时间:2014-07-03 14:19:19

标签: php mysql sql

我正在学习mysql,我有2个表,我必须比较table1主键和table2主键,在成功匹配时我需要从table2得到日期最小值和最大值为此我尝试了这些命令,虽然我得到了结果但是如果有任何好办法处理这种情况,请告诉我。

日期格式是这样的

   mysql> select sdate from table2
   | 27-Apr-2000 11:50:00 AM |
   | 27-Apr-2000 10:20:00 AM |
   | 27-Apr-2000 08:30:00 AM |
   | 20-Jan-1999 12:00:00 PM |

我试过的命令

   mysql> select min(str_to_date(m.sdate,'%d-%M-%Y')) as date_min, max(str_to_date(m.sdate,'%d-%M-%Y')) as date_max from ( select distinct p.key1 as key1, p.key2 as key2 from table1 as p ) as T inner join table2 as m on T.key1 = m.key1 and T.key2 = m.key2 where m.sdate !='';
   +------------+------------+
   | date_min   | date_max   |
   +------------+------------+
   | 1989-02-24 | 2011-12-30 |
   +------------+------------+
   1 row in set, 11396 warnings (18.95 sec)


   mysql> select min(str_to_date(m.sdate,'%d-%M-%Y')) as date_min, max(str_to_date(m.sdate,'%d-%M-%Y')) as date_max from ( select p.key1 as key1, p.key2 as key2 from table1 as p ) as T inner join table2 as m on T.key1 = m.key1 and T.key2 = m.key2 where m.sdate !='';
   +------------+------------+
   | date_min   | date_max   |
   +------------+------------+
   | 1989-02-24 | 2011-12-30 |
   +------------+------------+
   1 row in set, 11442 warnings (18.78 sec)


   mysql> select min(str_to_date(m.sdate,'%d-%M-%Y')) as date_min, max(str_to_date(m.sdate,'%d-%M-%Y')) as date_max from table2 as m, table1 as p where p.key1 = m.key1 and p.key2 = m.key2 and m.sdate !='';
   +------------+------------+
   | date_min   | date_max   |
   +------------+------------+
   | 1989-02-24 | 2011-12-30 |
   +------------+------------+
   1 row in set, 11442 warnings (18.86 sec)

   mysql> 

2 个答案:

答案 0 :(得分:2)

所有查询都无法在VARCHAR sdate列上有效使用索引(即范围扫描操作),因为该列已“包装”在查询中的函数中。为了获得此表单查询的最佳性能,理想情况下sdate将是实际的MySQL DATETIMETIMESTAMP数据类型,甚至是规范格式的VARCHAR。如果是这种情况,优化器将能够有效地使用索引来快速定位“最小”和“最大”日期值,而无需为每个翻转行评估STR_TO_DATE函数。 table,并且避免需要排序操作来定位从函数返回的“最小”和“最大”值。

将(半咆哮)放在一边......


在一般情况下,要获得与您的问题中前两个查询相同的结果,可以选择Gordon Linoff的答案中建议的形式查询。

(我们注意前两个查询包含key2=key1谓词,第三个查询包含key2=key2谓词。)

如果table2中有大量行,并且这些行中的绝大多数都会“匹配”来自table1的行,并且相对较少的不同(key1,key2) } table2中的值,如果(key1,key2)中的table1元组是唯一的或几乎唯一的,

这种形式的查询有可能表现得更好:

SELECT MIN(q.sdate_min) AS date_min
     , MAX(q.sdate_max) AS date_max 
  FROM ( SELECT m.key1
              , m.key2
              , MIN(STR_TO_DATE(m.sdate,'%d-%M-%Y')) AS sdate_min
              , MAX(STR_TO_DATE(m.sdate,'%d-%M-%Y')) AS sdate_max
           FROM table2 m
          GROUP
             BY m.key1
              , m.key2
       ) q
  JOIN table1 t
    ON t.key1 = q.key1
   AND t.key2 = q.key2

要提高内联视图查询的效果,您需要table2上的索引,其前导列为key1key2(按任意顺序排列),还包括sdate列。例如:

... ON table2 (key1, key2, sdate)

要提高JOIN操作的效果,您需要table1上的索引,key1key2作为索引中的前导列。例如:

... ON table1 (key1,key2)

... ON table1 (key2,key1)

(这假设您将在第三个查询中使用表单的谓词,即key1 = key1和key2 = key ** 2 **

如果您将使用形式为key1 = key1和key2 = key ** 1 **的谓词,那么我们将相应地调整查询和索引。

答案 1 :(得分:1)

您可以尝试这种方法:

select min(str_to_date(m.sdate,'%d-%M-%Y')) as date_min,
       max(str_to_date(m.sdate,'%d-%M-%Y')) as date_max
from table2 m
where exists (select 1
              from table1 t
              where t.key1 = m.key1 and t.key1 = m.key2
             );

然后,在table1(key1, key2)上创建一个索引以获得性能。