【问题标题】:SQL take max of similar id's from joinSQL 从连接中获取最大的相似 ID
【发布时间】:2015-07-21 15:58:20
【问题描述】:

我对更高级的 SQL 查询还很陌生

鉴于以下表格和相关字段:

PersonId、名字、姓氏

订购 OrderId、PersonId、OrderDateTime

我想编写一个查询,通过 PersonId 连接两个表,并检索每个人及其最近的订单。

所以如果下面的 James Doe (PersonId = 1) 在订单表中有很多订单,

OrderId、PersonId、OrderDateTime

1          1          12/1/2013 9:01 AM

2          1          2/1/2011 5:01 AM

3          2          10/1/2010 1:10 AM

他只需要最近的。

PersonId NameFirst NameLast OrderId OrderDateTime

1 James Doe 1    12/1/2013 9:01 AM 

2 John Doe 3     10/1/2010 1:10 AM 

我一直在尝试这样的事情

SELECT p.PersonID, o.OrderID, MAX(o.OrderDateTime) From Person p
JOIN Orders o ON p.PersonID = o.PersonID
GROUP BY p.PersonID,

谢谢

【问题讨论】:

  • 除非你真的同时使用 MySQL 和 SQL Server,否则只标记你实际使用的 dbms 的标签。

标签: mysql sql-server


【解决方案1】:

此解决方案中的内部查询是一个临时表,其中包含每个人的最新订单。我将它加入到Orders 表中以获取您想要的字段,然后再次加入到Person 表中。

SELECT p.PersonID, p.NameFirst, p.NameLast, o.OrderID, o.OrderDateTime
FROM Person p INNER JOIN Orders o
ON o.PersonId = p.PersonId
INNER JOIN
(
    SELECT o1.PersonId, MAX(o1.OrderDateTime) AS maxTime
    FROM Orders o1
    GROUP BY o1.PersonId
) t
ON o.PersonId = t.PersonId AND o.OrderDateTime = t.maxTime

【讨论】:

  • @jpw 你是完全正确的。我更新了我的查询。
  • 我打赌他使用的是 MySQL,如果他使用的是 SQL-Server,G-d 会帮助我们所有人。
  • @Tim Biegeleisen 好的,这就是我想知道的,只是不知道我是否知道我在说什么。但这是有道理的,这是一个很好的答案,我非常感谢你
  • 我同时使用两台不同的计算机。但是对于这个问题,我实际上并没有使用任何东西,但这只是一个概念性的东西
【解决方案2】:

您可以使用变量来模拟 MySQL 中不可用的ROW_NUMBER

SELECT p.PersonId, FirstName, LastName, 
       o.OrderId, o.OrderDateTime
FROM Person AS p
LEFT JOIN (
  SELECT OrderId, OrderDateTime, PersonId,
         @row_number := IF(@pid <> PersonId,
                           IF(@pid:=PersonId, 1, 1),
                           IF(@pid:=PersonId, @row_number+1, @row_number+1)) AS rn
  FROM `Order`
  CROSS JOIN (SELECT @row_number := 0, @pid := 0) vars
  ORDER BY OrderDateTime DESC
) AS o  ON p.PersonId = o.PersonId AND o.rn = 1

rn = 1 用于派生表的每个 PersonId 切片内的顶级记录。在LEFT JOINON 子句中使用此谓词,我们可以将Person 的每一行与Order 的最新行匹配,并获得所有 Order 字段。

Demo here

编辑:

在 SQL-Server 中,查询如下所示:

SELECT p.*, o.OrderId, o.OrderDateTime
FROM Person AS p
LEFT JOIN (
   SELECT *, 
          ROW_NUMBER() OVER (PARTITION BY PersonId 
                             ORDER BY OrderDateTime DESC) AS rn
   FROM [Order]
) AS o ON p.PersonId = o.PersonId AND o.rn = 1

【讨论】:

    【解决方案3】:

    所以每个人最近的订单。你可以这样做:

    select p.*, o.*
    from person p
    inner join orders o on p.personId = o.personId
    inner join (
        -- get the max order per person
        SELECT max(orderId) as orderId, personId
        from orders
        group by personId
    ) maxOrder on o.orderId = maxOrder.orderId
    

    orderId 上将o 加入maxOrder 将结果集过滤到同时也是每位客户最大订单的订单。

    请注意,我在表格上使用了ID 而不是日期时间,因为 ID 保证是唯一的(用于连接帮助) - 这并不总是可用的,具体取决于表格中使用的性质,但它看起来应该适合你的情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-11-19
      • 1970-01-01
      • 2020-09-15
      • 1970-01-01
      • 2021-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多