【问题标题】:SQL find latest dates, why do we need the 'inner join'SQL查找最新日期,为什么我们需要“内部连接”
【发布时间】:2016-08-21 17:50:06
【问题描述】:

我正在尝试使用 SQL 获取最新结果。我搜索了该网站,并从“stackoverflow”中找到了这篇旧帖子,链接:

SQL query to get most recent row for each instance of a given key

我在这里复制了最被接受的答案。

Select u.[username]
      ,u.[ip]
      ,q.[time_stamp]
From [users] As u
Inner Join (
    Select [username]
          ,max(time_stamp) as [time_stamp]
    From [users]
    Group By [username]) As [q]
On u.username = q.username
And u.time_stamp = q.time_stamp

我不明白的是为什么我们不能简单地在下面使用(即:为什么在这种情况下需要“内连接”操作)?

Select username, ip, max(time_stamp) as time_stamp
    From users
    Group By username

【问题讨论】:

  • (1) 用您正在使用的数据库标记您的问题。 (2) 它不起作用。在几乎所有数据库中,它都会返回语法错误,因为ip 不包含在GROUP BY 中,因此 SQL 引擎不知道要选择哪个值(MySQL 接受语法但插入不确定行中的值) .
  • 一般 GROUP BY 规则说:如果指定了 GROUP BY 子句,则 SELECT 列表中的每个列引用必须标识一个分组列或者是一个集合函数的参数。

标签: sql database


【解决方案1】:

大多数 SQL 变体(我相信 MySQL 除外)都要求您的 SELECT 列表中的任何非聚合列也必须在您的 GROUP BY 中。否则,对于具有多个 ip 值的单个 username,结果中应该出现哪一个?在这种情况下,您可能知道用户名/IP 对是唯一的,但 SQL 引擎可能并不总是知道这一点,尤其是对于更复杂的查询。

举个例子来说明:

用户:

username      ip              timestamp
--------      --------------  ---------
bob           167.49.122.122  2016-01-05
john          167.49.122.123  2016-02-02
bob           167.49.122.124  2016-04-01

您希望看到什么结果?对于“鲍勃”

应该是 bob/167.49.122.122/2016-04-01 吗?鲍勃/167.49.122.124/2016-04-01?两者都有?

您可能会说,“好吧,显然我想要具有最大日期的整行”,但从您的第二个 SELECT 来看,这并不明显,即使它对人类来说似乎很直观。

【讨论】:

  • 好答案。我要补充一点,如果您知道用户名/IP 对是唯一的,您可以使用带有GROUP BY username, ip 的简单查询。否则,您必须使用一种更复杂的方法来获得正确的 ip 值。
【解决方案2】:

您的语法建议使用 SQL Server(或者可能是 MS Access,但我会很乐观)。 ANSI 标准 SQL 中的一个典型方法是使用row_number()

select u.*
from (select u.*,
             row_number() over (partition by username order by time_stamp desc) as seqnum
      from users u
     ) u
where seqnum = 1;

当然还有其他方法不需要明确的join

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-01-04
    • 2012-01-03
    • 1970-01-01
    • 1970-01-01
    • 2013-04-12
    • 1970-01-01
    • 2019-06-09
    • 2018-06-29
    相关资源
    最近更新 更多