【问题标题】:GROUP BY, ORDER BY - How to make group by consider latest apperance of itemGROUP BY, ORDER BY - 如何根据项目的最新外观进行分组
【发布时间】:2009-05-13 09:37:13
【问题描述】:

我有一个这样的查询(Mysql 5.X,PHP - 为易读而格式化)

$query ="
SELECT 
  p.p_pid, 
  p.p_name, 
  p.p_url 
FROM 
  activity a, 
  products p 
WHERE 
  a.a_uid= ".$uid_int." 
  AND a.a_pid > 0 
  AND p.p_pid = a.a_pid 
GROUP BY 
  a.a_pid 
ORDER BY 
  a.a_time DESC LIMIT 6
");

一般来说,它应该生成用户看过的 6 种最新产品的唯一列表。

问题在于,如果用户不止一次地看过一个产品。其中一个在最近 6 个活动中,其中一个在最近 6 个活动之前查询不返回产品。我假设 (group by) 不会在 a_time 中留下产品的最新出现时间。我该如何纠正?

【问题讨论】:

    标签: sql mysql


    【解决方案1】:

    您是否尝试过按 MAX(a.a_time) 排序?

    SELECT 
      p.p_pid, 
      p.p_name, 
      p.p_url 
    FROM products p 
    INNER JOIN activity a on p.p_pid = a.a_pid 
    WHERE 
      a.a_uid= ".$uid_int." 
    GROUP BY 
      p_pid, p_name, p_url
    ORDER BY 
      max(a.a_time) DESC 
      LIMIT 6
    

    作为最佳做法,对您使用的每一列都使用 GROUP BY,而不使用聚合。 MySQL 是少数允许您使用未分组的列的数据库之一。它会从您选择的行中为您提供一个随机列。

    【讨论】:

      【解决方案2】:

      我当然希望$uid_int 变量被仔细检查是否存在 SQL 注入。

      $query ="
      SELECT 
        MAX(p.p_pid)  p_pid, 
        MAX(p.p_name) p_name, 
        MAX(p.p_url)  p_url
      FROM 
        activity a
        INNER JOIN products p ON p.p_pid = a.a_pid 
      WHERE 
        a.a_uid= ".$uid_int." 
        AND a.a_pid > 0 
      GROUP BY 
        a.a_pid 
      ORDER BY 
        MAX(a.a_time) DESC 
      LIMIT 6
      ");
      

      有时我想知道 MySQL 允许在没有显式聚合的情况下进行分组是否是一个好的设计决策...

      【讨论】:

      • 谢谢!。为什么我需要在 p_name 等上使用 MAX ?这些是字符串。
      • 先也是这么写的,不过a.a_pid上的group by其实是p上的group。所以他似乎想按产品分组,并找到最后 6 个有活动的产品。
      • @Nir:这些是 not 字符串。这些是字符串,按a.a_pid 分组。这就是为什么您必须使用聚合函数来选择组中的一个字符串。尽管 MySQL 在这里允许一些草率,甚至可能看起来很方便 - 没有在适当的地方使用聚合函数是导致您的问题的原因。
      猜你喜欢
      • 2011-06-28
      • 1970-01-01
      • 2017-08-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-01-27
      相关资源
      最近更新 更多