根据第二张表获取每个组的最大值记录

时间:2019-01-14 10:44:03

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

这与Get records with max value for each group of grouped SQL results有关,除了必要的组在单独的表中。

假设我有几座建筑物,每座建筑物都有一些办公室,并且有些人“签到”这些办公室来工作。

此表称为“办公室”,将建筑物与办公室匹配:

building   office
---
Seuss      Yertle
Seuss      Cubbins
Milne      Pooh
Milne      Eeyore
Milne      Roo

此表称为“签到”,记录了人们在每个办公室工作的时间:

id   office   person   timestamp
---
1    Yertle   Aaron    100
2    Cubbins  Aaron    200
3    Pooh     Aaron    300
4    Cubbins  Charlie  300
5    Cubbins  Aaron    700
6    Eeyore   Beth     600
7    Pooh     Beth     400

我想为每个建筑工人组合生成一张表格,告诉我该签到是该建筑中该人最近的一次入住:

 building  person   checkin_id  office   timestamp
 ---
 Seuss     Aaron    5           Cubbins  700
 Milne     Aaron    3           Pooh     300
 Milne     Beth     6           Eeyore   600
 Seuss     Charlie  4           Cubbins  300

我不知道该怎么做。标准技巧包括在比较相关值时将表连接到自身,然后在没有较大值的情况下丢弃行。我假设我需要两个“ checkins”副本和两个“ buildings”副本,它们之间具有复杂的连接,但是我似乎无法在正确的位置显示NULL。

我正在使用MySQL,如果有帮助的话。

3 个答案:

答案 0 :(得分:1)

有一个使用group_concat()substring_index()的技巧,您可以使用一个group by来做到这一点:

select o.building, c.person,
       max(c.id) as checkinid,
       substring_index(group_concat(c.office order by timestamp desc), ',', 1) as office,
       max(c.timestamp) as timestamp
from offices o join
     checkins c
     on o.office = c.office
group by o.building, c.person;

此版本假定idtimestamp一起增加,因此max()可以同时使用。

此外,group_concat()(默认情况下)的中间结果限制为大约1,000个字符,因此,如果一个人/建筑物组合有很多办公室,或者如果办公室名字很长。当然,如果逗号出现在office名称中,则可以更改分隔符。

答案 1 :(得分:0)

使用相关子查询

 select b.* from
  (select o.building,c.person,c.id as checkinid,
   c.office,c.timestamp from
   offices o join checkins c
   on o.office=c.office
  ) b
  where b.timestamp = (select max(a.timestamp)
                      from (
                        select o.building,c.person,
                        c.office,c.timestamp from
                        offices o join checkins c
                        on o.office=c.office
                         ) as a  where a.building=b.building and  
                     a.person=b.person 
                   )
       order by person

输出

building    person  checkinid   office  timestamp
Milne       Aaron     3         Pooh     300
Seuss       Aaron     5         Cubbins  700
Milne       Beth      6         Eeyore   600
Seuss       Charlie   4         Cubbins  300

答案 2 :(得分:0)

要获得所需的结果,您必须创建一个表,其中包含每个办公室的所有签到位置(JOIN officescheckins),然后JOIN每个建筑物中每个人的最新签到表:

SELECT o.building, c.person, c.id AS checkin_id, c.office, c.timestamp
FROM offices o
JOIN checkins c ON c.office = o.office
JOIN (SELECT o.building, c.person, MAX(c.timestamp) AS timestamp
      FROM offices o
      JOIN checkins c ON c.office = o.office
      GROUP BY o.building, c.person) t ON t.building = o.building AND t.person = c.person AND t.timestamp = c.timestamp
ORDER BY c.person, c.office

输出:

building    person      checkin_id  office      timestamp
Seuss       Aaron       5           Cubbins     700
Milne       Aaron       3           Pooh        300
Milne       Beth        6           Eeyore      600
Seuss       Charlie     4           Cubbins     300

Demo on dbfiddle