Mysql 查询效率(多次选择)

Mysql 查询效率(多次选择),mysql,sql,greatest-n-per-group,Mysql,Sql,Greatest N Per Group,我有两个表,一个叫做customer\u records,另一个叫做customer\u actions 客户记录具有以下架构: CustomerID (auto increment, primary key) CustomerName ...etc... ActionID (auto increment, primary key) CustomerID (relates to customer_records) ActionType ActionTime (UNIX time stamp t

我有两个表,一个叫做
customer\u records
,另一个叫做
customer\u actions

客户记录
具有以下架构:

CustomerID (auto increment, primary key)
CustomerName
...etc...
ActionID (auto increment, primary key)
CustomerID (relates to customer_records)
ActionType
ActionTime (UNIX time stamp that the entry was made)
Note (TEXT type)
customer\u actions
具有以下架构:

CustomerID (auto increment, primary key)
CustomerName
...etc...
ActionID (auto increment, primary key)
CustomerID (relates to customer_records)
ActionType
ActionTime (UNIX time stamp that the entry was made)
Note (TEXT type)
每次用户对客户记录执行操作时,都会在
customer\u actions
中输入一个条目,用户有机会输入备注<代码>动作类型可以是几个值中的一个(如“指定更新”或“添加的案例信息”-只能是选项列表中的一个)

我希望能够显示
customer\u records
中的记录列表,其中最后一个
ActionType
是某个值

到目前为止,我已经搜索了整个网络,找到了这个怪物:

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\u records
中有近20000条记录)。有谁能给我一些建议,告诉我如何对这个庞大的查询进行排序,或者调整我的表以获得更快的结果?我正在使用MySQL。非常感谢您的帮助,谢谢


编辑:为了清楚起见,我需要查看上一次行动是“随便什么”的客户列表。

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

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

请注意,20000条记录不应该造成性能问题。请注意,我已经修改了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',但当您开始处理可能包含多个连接的大型查询时,这是一个好习惯(一旦开始这样做,这将非常有意义)
  • 使用联接时,始终在主键上联接

要按客户的最后一个操作筛选客户,您可以使用相关子查询

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'

也许我遗漏了一些东西,但是简单的连接和where子句有什么不对呢

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

除上述内容外,如果您要考虑这一点,那么我强烈建议您不要使用*而只使用您直接需要的列名(选择*是一个巨大的性能影响)此查询选择在某个时间点对其记录执行了“whatever”操作的所有客户,但我需要查看对其记录执行的最后一个操作是“whatever”的客户。对不起,我在我的原始帖子中不太清楚。这是否意味着如果客户的最后一个操作(按ActionDate)“无论”是否表示该客户不应被列出?对于列出的客户,您是否只想要该客户,或者他们的最后一个操作,或者他们的所有操作?@Dems如果客户的最新
ActionType
不是“无论”,则不应显示它们。对于具有最新
ActionType我需要从
客户_记录中获取他们的信息
——但这不需要在一个查询中全部涵盖。OP需要一个客户列表,其中他们在操作表中的最后一个条目是一个特定的操作。“他们在操作表中的最后一个条目”是此处缺少的部分。[但我必须通过评论确认。]啊,是的,我重新阅读了OP。“我想做的是显示来自客户_记录的记录列表,其中上一个ActionType为某个值。”这意味着我的回答:我错过的是后来的“它列出了每个客户ID及其上一个操作”
前100名
应该是
限制100名
,但我想OP可以解决这个问题:)但是,如果总是在主键上连接,我实际上并不同意。如果
actions
表有一个代理主键,OP所需的功能仍然需要在主键以外的字段上连接。我想说的是,由于MySQL将主键作为聚集索引,doi有真正的好处ng是这样,但是如果你的逻辑意味着你不能,请确保你有一个适当的索引。非常有效的点-现在将对此进行更多的思考。非常感谢。谢谢-第一个查询返回了预期的结果(太棒了!)但执行此操作花费了445秒:-|!第二个查询返回了一个空集。@JonnyKeogh-其中有两个拼写错误,现已更正。[您是否有关于customer_操作(CustomerID,ActionDate)的覆盖索引?]