【问题标题】:MySQL Join - Sorting data, grouping dataMySQL Join - 排序数据,分组数据
【发布时间】:2015-06-16 22:33:49
【问题描述】:

我有两张桌子:

twitterusers 表

twitter 增长表

我正在尝试加入这 2 个表,从 twitteruser 获取所有字段并从 twittergrowth 获取选择性字段,然后仅从该数据中获取最后 3 行。

预期输出:

电流输出:

即行在重复。我想要由 ID 或用户名以及最后一组时间戳唯一的行。所以它将是最后 3 行,具有最新的时间戳。

我可以乱写的代码是:

SELECT 
  t1.*,
  t2.new_followers_count,
  t2.new_friends_count,
  t2.new_timestamp     
FROM twitterusers t1 
JOIN twittergrowth t2 on (t1.username=t2.username)

搜索了相当多的页面/站点,但无法真正弄清楚如何去做。我将不胜感激任何帮助。 :)

另外,我想在最终结果中添加一个LIMIT 参数,以便对完整结果进行分页。

【问题讨论】:

  • 我目前使用 GROUP BY 获得前 3 行,而我正在寻找最后 3 行。new_timestamp 是变化的变量。虽然它在图像中被部分裁剪了。
  • 如果我添加一个ORDER BY t2.new_timestamp 会安排结果,但我不能再使用GROUP BY 来避免重复。 Mysql 不允许在GROUP BY 之前使用ORDER BY。所以我基本上被卡住了。
  • 为什么所有用户都得到相同的user_id?你想通过这个 id 和用户名组合唯一的行吗?
  • 这是从单个 user_id 输入的转储数据。我很抱歉。用户 ID 会有所不同。
  • 是的,我希望行通过 user_id 和 username 比较是唯一的,这会为每行提供最新的 new_timestamp 字段。

标签: php mysql join left-join


【解决方案1】:

首先,您需要在twittergrowth 表中的相同user_idusername 的组中找到最大new_timestamp(最新)。这是一个经典的分组最大问题,子查询tgmax 就是这样做的。然后,您需要重新连接同一个表(这次是tg)以获取不在子查询的 group by 子句中且未在聚合函数中使用的其他列(如 max())。这些列是new_followers_countnew_friends_count

如果您尝试将它们放在子查询的选择中,mysql 将返回来自同一组的未指定行的值,不一定与具有最新时间戳的行相同。这是解释here

一旦获得 twittergrowth 表的所需输出,剩下的就是加入 twitterusers 表以获取所有其他列。

SELECT tu.*, tg.new_followers_count, tg.new_friends_count, tg.new_timestamp
FROM twitterusers tu
JOIN twittergrowth tg
  ON tu.user_id = tg.user_id AND tu.username = tg.username
JOIN 
  ( SELECT tgg.user_id, tgg.username, max(tgg.new_timestamp) as latest_timestamp 
    FROM twittergrowth tgg
    GROUP BY tgg.user_id, tgg.username ) tgmax
  ON tg.user_id = tgmax.user_id AND tg.username = tgmax.username
    AND tg.new_timestamp = tgmax.latest_timestamp

请注意,此查询将受益于twittergrowth 表中(user_id,username,new_timestamp) 的复合索引。

【讨论】:

  • 该代码运行良好。您是否有一两分钟的时间来讨论我的数据库架构?我不会让它长。只是想看看我做事是否正确。
  • 架构在我看来没问题,如果您不确定,可以提出一个新问题。
  • 我有 2 个表是,一个表存储用户将用户名添加到我的系统时的信息。(这些数据永远不会再改变)。另一个表跟踪更新,每次更新都有一个新行。这是正确的做法吗?
  • 如果您需要更改历史记录,可以。
  • 是的。我需要变化的历史。所以这似乎是一个很好的模式来做我想做的事?
【解决方案2】:

您需要分组以实现您的预​​期输出。

GROUP BY id

要将结果限制或拆分为页面,您可以简单地添加LIMIT X,Y,其中 X 是起始记录,Y 是记录总数。

所以一个查询来提取你想要的预期结果,但只有前 10 个是这样的:

SELECT 
  t1.*,
  t2.new_followers_count,
  t2.new_friends_count,
  t2.new_timestamp     
FROM twitterusers t1 
JOIN twittergrowth t2 on t1.username=t2.username 
GROUP BY t1.id
LIMIT 0,10

【讨论】:

  • 我现在刚刚编辑了我的问题。你能再检查一次预期的输出吗?我实际上想要最后 3 行。目前,我得到了前 3 行。
  • 根据我正在阅读的内容,这应该是您想要的。 Group By 告诉 MySQL 将连接分组到一个唯一的列上。 IE。如果我想在结果中使用来自 twitteruser 的唯一 ID,那么我将按该表的 ID 进行分组。根据您显示的数据,总共只有 3 行?
  • 请检查最后一列new_timestamp 有一半被裁剪掉,但这是一个变化的值。所以我试图获取最后 3 行而不是前 3 行。
  • 您可以按多个值分组,先按 id 分组,然后按时间戳分组。 IE。 group by t1.id, timestamp_column您可以使用 ORDER 对数据进行排序,因此获取最后 3 项就像 order by timestamp_column desc limit 3 一样简单
  • 正如我作为对问题的评论添加的那样,我可以使用ORDER BY,但它不允许在ORDER BY 之后使用GROUP BY。我尝试按多个字段分组。没有给我预期的结果。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 2021-11-26
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多