慢查询检索最近的记录

时间:2016-06-14 17:54:43

标签: mysql

我在从历史记录表中检索最新记录时遇到困难。我现在正在处理检索的一部分。决赛将是最近历史记录条目与客户表的连接。

客户表格是:

CREATE TABLE Clients
 (
        id                      int(8) auto_increment not null primary key, 
        LastName                varchar(50), 
        First                  varchar(50),
        CanContact             TINYINT(1)
);

客户历史记录(约300,000条记录):

CREATE TABLE ClientHistory
(
        id                      int(8) auto_increment not null primary key, 
        Client                  int(8),
        Act_Date                datetime,
        Activity                int(8)
);
create index idx_ClientHistory_Client on ClientHistory(Client);
create index idx_ClientHistory_Act_Date on ClientHistory(Act_Date);

问题1: SELECT id, MAX(Act_Date), Notes from ClientHistory group by Client。这将检索最新的日期,但id和Notes实际上来自最早的记录。

mysql> select id, Client, Act_Date, Activity from ClientHistory where client=18176;
+--------+--------+---------------------+----------+
| id     | Client | Act_Date            | Activity |
+--------+--------+---------------------+----------+
| 346725 |  18176 | 2015-09-04 09:29:35 |        4 |
| 346726 |  18176 | 2015-09-04 09:29:39 |        3 |
| 346727 |  18176 | 2015-09-04 09:44:29 |        4 |
| 346728 |  18176 | 2015-09-04 09:44:36 |        3 |
| 346737 |  18176 | 2015-09-04 10:35:10 |        4 |
| 346739 |  18176 | 2015-09-04 10:49:43 |        4 |
| 346740 |  18176 | 2015-09-04 10:54:57 |       29 |
| 346787 |  18176 | 2015-09-04 15:37:15 |       23 |
| 346788 |  18176 | 2015-09-04 15:37:20 |       23 |
| 346789 |  18176 | 2015-09-04 15:37:23 |       23 |
| 346790 |  18176 | 2015-09-04 15:37:27 |       23 |
| 346791 |  18176 | 2015-09-04 15:37:30 |       23 |
| 346792 |  18176 | 2015-09-04 15:37:34 |       20 |
| 346793 |  18176 | 2015-09-04 15:37:51 |       13 |
| 346798 |  18176 | 2015-09-04 15:50:51 |       25 |
| 346808 |  18176 | 2015-09-04 16:10:55 |       13 |
+--------+--------+---------------------+----------+
16 rows in set (0.00 sec)

mysql> select id, Client, Act_Date, MAX(Act_Date), Activity from ClientHistory where client=18176;
+--------+--------+---------------------+---------------------+----------+
| id     | Client | Act_Date            | MAX(Act_Date)       | Activity |
+--------+--------+---------------------+---------------------+----------+
| 346725 |  18176 | 2015-09-04 09:29:35 | 2015-09-04 16:10:55 |        4 |
+--------+--------+---------------------+---------------------+----------+
1 row in set (0.00 sec)

mysql> select id, Client, Act_Date, Activity from ClientHistory where client=18176 group by Client order by Act_Date desc;
+--------+--------+---------------------+----------+
| id     | Client | Act_Date            | Activity |
+--------+--------+---------------------+----------+
| 346725 |  18176 | 2015-09-04 09:29:35 |        4 |
+--------+--------+---------------------+----------+
1 row in set (0.00 sec)

问题2 以下查询非常慢(~6秒):

select * from Clients
LEFT JOIN ( 
    select c1.* from ClientHistory as c1
        LEFT JOIN ClientHistory as c2 on c1.client = c2.client and c1.Act_Date < c2.Act_Date where c2.Client is null
        ) as ctemp on Clients.id = ctemp.Client
        where CanContact=true order by LastName, First;

罪魁祸首是:

select c1.* from ClientHistory as c1
        LEFT JOIN ClientHistory as c2 on c1.client = c2.client and c1.Act_Date < c2.Act_Date where c2.Client is null;
And the explain:
explain select c1.* from ClientHistory as c1 LEFT JOIN ClientHistory as c2 on c1.client = c2.client and c1.Act_Date < c2.Act_Date where c2.Client is null;
+----+-------------+-------+------+-----------------------------------------------------+--------------------------+---------+-----------+--------+-------------+
| id | select_type | table | type | possible_keys                                       | key                      | key_len | ref       | rows   | Extra       |
+----+-------------+-------+------+-----------------------------------------------------+--------------------------+---------+-----------+--------+-------------+
|  1 | SIMPLE      | c1    | ALL  | NULL                                                | NULL                     | NULL    | NULL      | 330120 | NULL        |
|  1 | SIMPLE      | c2    | ref  | idx_ClientHistory_Client,idx_ClientHistory_Act_Date | idx_ClientHistory_Client | 5       | c1.Client |      8 | Using where |
+----+-------------+-------+------+-----------------------------------------------------+--------------------------+---------+-----------+--------+-------------+
2 rows in set (0.00 sec)

我感到非常困惑。

2 个答案:

答案 0 :(得分:0)

回答问题1:

SELECT id, MAX(Act_Date), Notes from ClientHistory group by Client

不符合ANSI标准。您必须在GROUP BY子句

中列出所有没有应用函数的列

在这种情况下,由于MAX(Act_Date)对于单个客户端可能是多个,因此可能会返回多于1条记录。如果您的数据不是这种情况,您可以使用:

SELECT Client,MAX(id), MAX(Act_Date) from ClientHistory group by Client

Notes是一个更难以检索的字段,但是现在你有了id,你可以通过id将表连接回来来检索它。

答案 1 :(得分:0)

你可以在哪里进行和加入

SELECT  * from ClientHistory 
where (Act_Date, client) in ( select MAX(Act_Date), client)
   from ClientHistory group by Client) 
inner join client on client.id = ClientHistory .client;