每个左连接返回1个结果

时间:2010-09-20 00:04:33

标签: sql join greatest-n-per-group

目前我正在两个表上执行左连接。第一个表有一个id和一个人名,第二个表有一个id,一个人的id来自表1,然后是一个时间戳(一个航班)。

People                             Flights
id   |  name             id   |   person_id   | time
------------             ---------------------------
1       Dave              1         1          1284762115
2       Becky             2         1          1284787352
                          3         2          1284772629
                          4         2          1286432934
                          5         1          1283239480

当我执行左连接时,我会得到一个人员列表和他们的航班时间,但我想要的只是航班时间且ID最高的人员列表

我一直在使用

   SELECT p.id, p.name max(f.time) 
     FROM People p 
LEFT JOIN Flights f ON p.id = f.person_id
 GROUP BY p.id, p.name

然而,这只是给我最后的飞行时间,而不是上传到系统的最后一次飞行时间(即最高ID)。

1 Dave  1284787352
2 Becky 1286432934

重申一下,我希望看到该人的姓名,以及他们上次上传(最高身份证)航班时间的飞行时间。

1 Dave  1283239480
2 Becky 1286432934

2 个答案:

答案 0 :(得分:6)

使用:

SELECT p.id,
       p.name,
       f.time
  FROM PEOPLE p
  JOIN FLIGHTS f ON f.person_id = p.id
  JOIN (SELECT f.person_id,
               MAX(f.id) AS max_id
          FROM FLIGHTS f
      GROUP BY f.person_id) x ON x.person_id = f.person_id
                             AND x.max_id = f.id

如果您使用的是支持分析的数据库:

SELECT p.id,
       p.name,
       x.time
  FROM PEOPLE p
  JOIN (SELECT f.person_id,
               f.time,
               ROW_NUMBER() OVER(PARTITION BY f.person_id
                                     ORDER BY f.id DESC) AS rk
          FROM FLIGHTS f) x ON x.person_id = p.id
                           AND x.rk = 1

如果你想要人,包括那些没有航班的人:

   SELECT p.id,
          p.name,
          f.time
     FROM PEOPLE p
LEFT JOIN FLIGHTS f ON f.person_id = p.id
     JOIN (SELECT f.person_id,
                  MAX(f.id) AS max_id
             FROM FLIGHTS f
         GROUP BY f.person_id) x ON x.person_id = f.person_id
                                AND x.max_id = f.id

...和分析版本:

   SELECT p.id,
          p.name,
          x.time
     FROM PEOPLE p
LEFT JOIN (SELECT f.person_id,
                  f.time,
                  ROW_NUMBER() OVER(PARTITION BY f.person_id
                                        ORDER BY f.id DESC) AS rk
             FROM FLIGHTS f) x ON x.person_id = p.id
                              AND x.rk = 1

答案 1 :(得分:1)

我认为您正在寻找类似下面的内容。按person_id分组并选择最大ID,然后使用该列表从航班中进行选择。这是我第一次想到可能会有更好的方式。

编辑:

SELECT p.id, p.name MAX(f.time)  
     FROM People p  
LEFT JOIN Flights f ON p.id = f.person_id 
WHERE f.id in(SELECT MAX(id) FROM flights GROUP BY person_id)