【问题标题】:mysql - join table row based on id with the highest column value in the table - multiple joins and conditionsmysql - 根据表中列值最高的 id 连接表行 - 多个连接和条件
【发布时间】:2020-12-11 09:44:48
【问题描述】:

我在询问之前搜索了 SO,并尝试了我发现的东西 - 由于多个连接和条件,我参与的更多,无法获得正确的结果。

SQL Fiddle here 已输入基本数据。

下面的查询没有给出我想要的结果,但给出了我想要实现的目标。我想为每个 computer_id 返回 1 个结果,其中 time.capture_timestamp 介于特定的开始/结束值之间,并且是该计算机 ID 的表中的最大值,包括该行的其他列值。我已经尝试了一些我在这里找到的涉及 MAX() 和子查询的不同的东西,但似乎无法得到我想要的东西。

SELECT
  computers.computer_name,
  users.username,
  time.title,
  time.capture_timestamp
FROM computers
INNER JOIN time
  ON time.computer_id = computers.computer_id AND time.capture_timestamp >= 0 AND time.capture_timestamp <= 9999999999
INNER JOIN users
  ON users.user_id = time.user_id
GROUP BY computers.computer_id
ORDER BY time.capture_timestamp DESC

小提琴原样返回:

computer_name   username    title           capture_timestamp
computer1       user1       some title      1595524341
computer2       user3       some title3     1595524331

而我想要的结果实际上是:

computer_name   username    title           capture_timestamp
computer1       user2       some title2     1595524351
computer2       user3       some title3     1595524331

... 基于小提琴中的示例值。是的,在此示例中,开始/结束时间值包括“所有内容”,但在使用中实际上会提供时间戳范围。

【问题讨论】:

    标签: mysql greatest-n-per-group


    【解决方案1】:

    使用ROW_NUMBER

    WITH cte AS (
        SELECT c.computer_name, u.username, t.title, t.capture_timestamp,
               ROW_NUMBER() OVER (PARTITION BY c.computer_id
                                  ORDER BY t.capture_timestamp DESC) rn
        FROM computers c
        INNER JOIN time t ON t.computer_id = c.computer_id
        INNER JOIN users u ON u.user_id = t.user_id
        WHERE t.capture_timestamp BETWEEN 0 AND 9999999999
    )
    
    SELECT computer_name, username, title, capture_timestamp
    FROM cte
    WHERE rn = 1;
    

    【讨论】:

    • 如果没有先看到它,绝对不会想到这一点。如果我理解正确,它只是在临时分区中对capture_timestamp 进行排序,然后只选择该分区中的第一行?订购 ASC 将给出找到的最小值。除了说出此处显示的其他答案之外,还有什么特殊原因使用这种方式吗?
    • 我不明白你的评论,但假设你在 MySQL 8+ 上,我上面给出的版本可能是最好的方法。如果您使用的是早期版本,请使用@MKhalid 的答案。
    【解决方案2】:

    您可以添加相关子查询以获得所需的结果

    select
      computers.computer_name,
      users.username,
      t.title,
      t.capture_timestamp
    from computers
    inner join time t
      on t.computer_id = computers.computer_id 
      and t.capture_timestamp >= 0 and t.capture_timestamp <= 9999999999
    inner join users
      on users.user_id = t.user_id
    where t.capture_timestamp =(
      select max(capture_timestamp)
      from time
      where capture_timestamp >= 0 and capture_timestamp <= 9999999999
      and t.computer_id = computer_id
    )
    order by t.capture_timestamp desc
    

    DEMO

    【讨论】:

    • 谢谢。这看起来与我根据 SO 上的其他帖子所尝试的几乎相同,但无法达到预期的结果。不过,这确实得到了正确的结果。
    猜你喜欢
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-19
    • 1970-01-01
    • 2020-04-05
    • 1970-01-01
    相关资源
    最近更新 更多