查询效率(多选)

时间:2011-12-23 00:23:16

标签: mysql sql greatest-n-per-group

我有两个表 - 一个名为customer_records,另一个名为customer_actions

customer_records具有以下架构:

CustomerID (auto increment, primary key)
CustomerName
...etc...

customer_actions具有以下架构:

ActionID (auto increment, primary key)
CustomerID (relates to customer_records)
ActionType
ActionTime (UNIX time stamp that the entry was made)
Note (TEXT type)

每次用户对客户记录执行操作时,都会在customer_actions中输入一个条目,并且用户有机会输入记事。 ActionType可以是少数值之一(例如“指定更新”或“添加案例信息” - 只能是选项列表中的一个)。

我希望能够做的是显示customer_records中最后ActionType为特定值的记录列表。

到目前为止,我已经搜索了网/ SO并想出了这个怪物:

SELECT * FROM (
    SELECT * FROM (
        SELECT * FROM `customer_actions` ORDER BY `EntryID` DESC
    ) list1 GROUP BY `CustomerID`
) list2 WHERE `ActionType`='whatever' LIMIT 0,30

哪个好 - 它列出了每个客户ID及其最后一个操作。但是查询在某些情况下非常缓慢(注意:customer_records中有近20,000条记录)。任何人都可以提供任何关于我如何对这个查询怪物进行排序或调整我的表以提供更快结果的提示?我正在使用MySQL。非常感谢任何帮助,谢谢。

编辑:要明确的是,我需要查看最后一次操作的客户列表是“什么”。

4 个答案:

答案 0 :(得分:5)

要按客户的上一个操作过滤客户,您可以使用相关的子查询...

SELECT
  *
FROM
  customer_records
INNER JOIN
  customer_actions
    ON  customer_actions.CustomerID = customer_records.CustomerID
    AND customer_actions.ActionDate = (
           SELECT
             MAX(ActionDate)
           FROM
             customer_actions  AS lookup
           WHERE
             CustomerID = customer_records.CustomerID
        )
WHERE
  customer_actions.ActionType = 'Whatever'

您可能会发现避免相关子查询更有效,如下所示......

SELECT
  *
FROM
  customer_records
INNER JOIN
  (SELECT CustomerID, MAX(ActionDate) AS ActionDate FROM customer_actions GROUP BY CustomerID) AS last_action
    ON customer_records.CustomerID = last_action.CustomerID
INNER JOIN
  customer_actions 
    ON  customer_actions.CustomerID = last_action.CustomerID
    AND customer_actions.ActionDate = last_action.ActionDate
WHERE
  customer_actions.ActionType = 'Whatever'

答案 1 :(得分:2)

我不确定我是否理解这些要求,但在我看来,JOIN就足够了。

SELECT  cr.CustomerID, cr.CustomerName, ...
FROM    customer_records cr
        INNER JOIN customer_actions ca ON ca.CustomerID = cr.CustomerID
WHERE   `ActionType` = 'whatever'
ORDER BY
        ca.EntryID

请注意,20.000条记录不应构成性能问题

答案 2 :(得分:2)

请注意我已经改编了Lieven的答案(我发了一个单独的帖子,因为这个评论太长了)。解决方案本身的任何功劳归于他,我只是想向您展示一些提高性能的关键点。

如果速度是一个问题,那么以下内容应该为您提供一些改进建议:

select top 100 -- Change as required
        cr.CustomerID ,
        cr.CustomerName,
        cr.MoreDetail1,
        cr.Etc
from    customer_records cr
        inner join customer_actions ca 
            on ca.CustomerID = cr.CustomerID
where   ca.ActionType = 'x'
order by cr.CustomerID

一些注意事项:

  • 在某些情况下,我发现左外连接比内连接更快 - 对于此查询,两者都值得测量性能
  • 尽可能避免返回*
  • 您不必在初始选择中引用'cr.x',但是当您开始处理可能有多个连接的大型查询时,这是一个很好的习惯(这会很有意义)一旦你开始这样做
  • 使用联接始终加入主键

答案 3 :(得分:1)

也许我错过了一些简单的连接和where子句有什么问题?

Select ActionType, ActionTime, Note
FROM Customer_Records CR
INNER JOIN customer_Actions CA 
  ON CR.CustomerID = CA.CustomerID
Where ActionType = 'added case info'