【问题标题】:How do I get distinct rows by a column?如何按列获取不同的行?
【发布时间】:2016-11-16 16:33:09
【问题描述】:

我有大量的行,我想说,从 10 个不同的用户插入到该数据库的最后 5 条记录。如果同一个用户将最后 3 行插入数据库,我们必须获取一行,跳过其他两行并移动以获取每个用户的一行,直到它计数到 5。

这样的数据库:

user_id | news_id | title
1       | 1       | foo-1
2       | 2       | foo-2
3       | 3       | foo-3
1       | 4       | baa
4       | 5       | baa0
5       | 6       | baa1
5       | 7       | baa2
6       | 8       | baa3
7       | 9       | baa4

应该返回:

user_id | news_id | title
1       | 1       | foo-1
2       | 2       | foo-2
3       | 3       | foo-3
4       | 5       | baa0
5       | 6       | baa1

当前的过滤器是由 PHP 完成的,像这样:

$used = array();
while ($data = mysql_fetch_array($query)) {
   $uid = $data['user_id'];
    if(in_array($uid, $used))
        continue;
    array_push($used, $uid);

// do something with data
}

但我想重构它,如果可能的话,纯粹用mysql做过滤。我不太了解 MySql,这就是为什么我无法归档这个...

这是我尝试过的

select DISTINCT(user_id), news_id, title from XXX
WHERE GROUP BY (news_id) DESC
LIMIT 0,5

我该怎么做?

【问题讨论】:

  • 删除 WHERE。你也不需要 DISTINCT。
  • WHERE GROUP BY 会抛出错误mysql_error()。阅读有关 SELECT dev.mysql.com/doc/refman/5.7/en/select.html 的手册 - 您还缺少 FROM table
  • 请不要再使用mysql_*函数了。它们在 PHP 5.5 中被弃用,它太旧了,不再接收安全更新,并在 PHP 7 中完全删除。改用 PDO 或mysqli_*。详情请见stackoverflow.com/questions/12859942/…
  • @aynber:没有它的工作位置,但问题是..我在数据库中有值为 0 的 user_id(它不是由我插入的,我只是在上面实现新的例程网站),我还需要过滤。我怎样才能删除它们?
  • @Chris:这是我正在维护的旧代码库的一部分,我会编辑它,至少现在不会,但无论如何谢谢

标签: php mysql sql distinct


【解决方案1】:

一种方法是为每个用户生成一个分区行号,然后选择 5 条记录,其中 RowNumber = 1。

SELECT *
FROM
  (
    SELECT
      d.user_id
      ,d.news_id
      ,d.title
      ,(@rn:= if(@uid = user_id, @rn + 1,
                 if(@uid:=user_id,1,1)
                 )
        ) as RowNumber
    FROM
      Data d
      CROSS JOIN (SELECT @uid:=-1, @rn:=0) vars
    ORDER BY
      user_id
      ,news_id
) t
WHERE
  t.RowNumber = 1
ORDER BY news_id
LIMIT 5;

http://rextester.com/JRIZI7402 - 展示它工作的示例

请注意,您可以通过简单地更改派生表的 ORDER BY 语句来更改行顺序,因此如果您有一个表示最新记录的列,例如您可以使用标识列或日期时间列,但 user_id 必须是正确分区的第一个条件。

【讨论】:

  • 惊人的答案!我还有一个问题,我正在尝试更改行顺序,以便返回最新的新闻(和最旧的新闻),例如,返回 id 107, 109, 112 等的新闻,其中最新的新闻 id就像4003, 4002, 4001, 400 等我如何更改ORDER BY 以返回这些行?我试过按日期列过滤,但它是字符串类型(实际上是 varchar)而不是日期时间(它不是我设计的,我只是对此进行维护)...
  • @Jack 感谢颠倒 news_id 的顺序以先获取最新信息,只需在 ORDER BY 中的 news_id 之后添加 DESC 即可。要使用 varchar 日期列,您可以使用 STR_TO_DATE() stackoverflow.com/questions/15396058/… 如果我的回答帮助您解决了这个问题,请投票并接受,以便其他人知道您有您需要的东西,谢谢。
  • @Jack ORDER BY user_id, news_id DESC
  • ORDER BY user_id ,news_id , STR_TO_DATE(...) 会把最新消息放在首位吗?
  • @Jack 可能是这个 ORDER BY user_id, STR_TO_DATE(...) DESC
【解决方案2】:

从您的查询中执行。

"SELECT * FROM table GROUP BY user_id ORDER BY news_id DESC LIMIT 5"

【讨论】:

    【解决方案3】:

    好吧,我认为这将实现您的目标。

    select user_id, news_id, title from tableName
       GROUP BY user_id 
       ORDER BY news_id DESC
       LIMIT 0,5
    

    希望这会有所帮助!

    【讨论】:

    猜你喜欢
    • 2023-03-24
    • 2019-10-11
    • 2021-08-02
    • 1970-01-01
    • 2011-07-06
    • 1970-01-01
    • 2013-12-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多