【问题标题】:Retrieving the last filtered record in each group检索每个组中最后过滤的记录
【发布时间】:2012-08-23 13:44:39
【问题描述】:

不久前我读到了@Bill Karwin 的出色回答:

https://stackoverflow.com/a/1313293/317889

这几乎回答了这个问题,但是我最近不得不更新我的查询以过滤连接表的状态。

我在下面写了两个查询,类似于上面帖子中的查询。第一个较慢的查询与联接表状态过滤一起使用:

SELECT m.*, t1.* FROM mood m 
LEFT JOIN temper t ON ( m._id = t.mood_id ) 
WHERE grantee_username = "username" 
AND m.status_id != 1 // NOT INTERESTED IN THIS FILTER
AND t.status_id != 1 // FILTERING 
GROUP BY m._id;

对于第二个查询,我不知道如何添加过滤以使其按上述方式工作:

SELECT m.*, t1.* FROM mood m 
LEFT JOIN temper t1 ON ( m._id = t1.mood_id ) 
LEFT JOIN temper t2 ON ( t1.mood_id = t2.mood_id AND t1._id < t2._id ) 
WHERE t2._id IS NULL 
AND m.grantee_username = "username" 
AND m.status_id != 1; // NOT INTERESTED IN THIS FILTER

第一个查询完美运行,但被认为比第二个查询慢。

第二个查询用于将所有情绪记录及其相关的上次脾气记录带回,但是上次脾气记录可能具有我不想要的状态 1。

任何见解都会很有趣。我总是可以只使用第一个查询,但为了性能起见,我想弄清楚如何在可能的情况下将t.status_id 过滤添加到第二个查询中。

【问题讨论】:

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


    【解决方案1】:

    我认为您的第二个查询最后缺少 GROUP BY。

    这个版本在子查询中增加了过滤器:

    SELECT m.*, t1.*
    FROM mood m  LEFT JOIN
         (select t.*
          from temper t
          where t.status_id != 1
         ) t1
         ON m._id = t1.mood_id  LEFT JOIN
         temper t2
         ON t1.mood_id = t2.mood_id AND t1._id < t2._id
    WHERE t2._id IS NULL AND
          m.grantee_username = "username" 
    GROUP BY m._id;
    

    您还想要 t2 上的过滤器吗?

    顺便说一句,您在 MySQl 中使用了一个名为 Hidden Columns 的功能——您在一个列上进行聚合,但在其他列上返回行,没有聚合函数。此功能仅在 MySQL 中。

    【讨论】:

    • 感谢您的回复。实际上应该不需要 group by。成功抓取到正确的脾气记录 问题是最后一次脾气记录的状态可能是我不想要的1。
    • 所以我已经运行了您的查询,但 JOIN 并不能正常工作。我的测试数据库有 3 条情绪记录,应该总是返回,我上面的两个查询都是这种情况。您的查询返回 1 条情绪记录,其中脾气状态不是 1。头痛!
    • 另外,我不确定在与我的第二个查询相比时,在查询中使用子选择是否会产生性能差异。
    • @haraldo ...你是对的。有更简洁的执行方式来编写这个查询。唉,我现在在移动设备上,无法输入。
    【解决方案2】:

    好吧,毕竟这不是太难:

    SELECT m.*, t1.* FROM mood m 
    LEFT JOIN temper t1 ON ( m._id = t1.mood_id AND t1.status_id !=1) 
    LEFT JOIN temper t2 ON ( t1.mood_id = t2.mood_id AND t1._id < t2._id AND t2.status_id !=1 ) 
    WHERE t2._id IS NULL 
    AND m.grantee_username = "username" 
    AND m.status_id != 1; // NOT INTERESTED IN THIS FILTER
    

    过滤器(status_id)需要添加到每个JOIN。

    【讨论】:

      猜你喜欢
      • 2010-11-21
      相关资源
      最近更新 更多