我想创建一个查询,其中包含每个玩家的最新信息。该查询应为每个玩家返回一个结果。如果玩家更改了其Gamertag,则查询结果应返回该玩家最近的非null Gamertag。此行为应扩展到其他标识符,例如城市,州和国家。以下是两个玩家的一些示例数据:
+-----------+-------------+-----------+--------+-----------+---------------+-------+
| player_id | recorded_at | gamertag | prefix | city | country | state |
+-----------+-------------+-----------+--------+-----------+---------------+-------+
| 26640 | 1461421800 | Wobbaduck | NULL | Toronto | Canada | ON |
| 26640 | 1484931600 | Wobbaduck | NULL | Saskatoon | Canada | SK |
| 26640 | 1510416000 | Mimic | NULL | NULL | NULL | NULL |
| 26640 | 1516388400 | Mimic | NULL | NULL | Canada | SK |
| 26640 | 1518278400 | Mimic | NULL | NULL | NULL | NULL |
| 4507 | 1491678000 | The Moon | NULL | NULL | NULL | NULL |
| 4507 | 1500645600 | The Moon | MVG | Buffalo | United States | NY |
| 4507 | 1533830400 | La Luna | NULL | New York | United States | NY |
+-----------+-------------+-----------+--------+-----------+---------------+-------+
查询应产生结果:
+-----------+----------+--------+-----------+---------------+-------+
| player_id | gamertag | prefix | city | country | state |
+-----------+----------+--------+-----------+---------------+-------+
| 26640 | Mimic | NULL | Saskatoon | Canada | SK |
| 4507 | La Luna | MVG | New York | United States | NY |
+-----------+----------+--------+-----------+---------------+-------+
字段recorded_at
用于跟踪以纪元秒为单位的日期。
我之前为实现此目的所做的尝试都包括了子查询和每个标识符gamertag
,prefix
,city
,country
和state
的联接。如果可能的话,我想避免这样做。
我正在使用MySQL 8.0.11。
我已经使用示例数据创建了一个db-fiddle。
答案 0 :(得分:0)
子查询有效填充,而外部查询则选择最后一个recorded_at
drop table if exists t;
create table t( player_id int, recorded_at int, gamertag varchar(20), prefix varchar(20), city varchar(20), country varchar(20)
, state varchar(20));
insert into t values
( 26640 , 1461421800 , 'Wobbaduck' , NULL , 'Toronto' , 'Canada' , 'ON') ,
( 26640 , 1484931600 , 'Wobbaduck' , NULL , 'Saskatoon' , 'Canada' , 'SK' ) ,
( 26640 , 1510416000 , 'Mimic' , NULL , NULL , NULL , NULL ) ,
( 26640 , 1516388400 , 'Mimic' , NULL , NULL , 'Canada' , 'SK' ) ,
( 26640 , 1518278400 , 'Mimic' , NULL , NULL , NULL , NULL ),
( 4507 , 1491678000 , 'The Moon' , NULL , NULL , NULL , NULL ),
( 4507 , 1500645600 , 'The Moon' , 'MVG' , 'Buffalo' , 'United States' , 'NY' ),
( 4507 , 1533830400 , 'La Luna' , NULL , 'New York' , 'United States' , 'NY' );
select *
from
(
select t.player_id,t.recorded_at,
if(t.gamertag is null,
(select t1.gamertag from t t1 where t1.gamertag is not null and t1.player_id = t.player_id and t1.recorded_at < t.recorded_at order by t1.recorded_at desc limit 1),
t.gamertag) gamertag,
if(t.prefix is null,
(select t1.prefix from t t1 where t1.prefix is not null and t1.player_id = t.player_id and t1.recorded_at < t.recorded_at order by t1.recorded_at desc limit 1),
t.prefix) prefix,
if(t.city is null,
(select t1.city from t t1 where t1.city is not null and t1.player_id = t.player_id and t1.recorded_at < t.recorded_at order by t1.recorded_at desc limit 1),
t.city) city,
if(t.country is null,
(select t1.country from t t1 where t1.country is not null and t1.player_id = t.player_id and t1.recorded_at < t.recorded_at order by t1.recorded_at desc limit 1),
t.country) country
from t
order by t.player_id, t.recorded_at
) s
where s.recorded_at = (select max(recorded_at) from t t1 where t1.player_id = s.player_id);
+-----------+-------------+----------+--------+-----------+---------------+
| player_id | recorded_at | gamertag | prefix | city | country |
+-----------+-------------+----------+--------+-----------+---------------+
| 26640 | 1518278400 | Mimic | NULL | Saskatoon | Canada |
| 4507 | 1533830400 | La Luna | MVG | New York | United States |
+-----------+-------------+----------+--------+-----------+---------------+
2 rows in set (0.00 sec)
答案 1 :(得分:0)
这并不是您想要的,但是我认为它可以工作。对于列,它为每个列获取一个逗号分隔的值列表。您所要做的只是获取第一个值,该值将是该列的最新值。
select *
from player a
JOIN (SELECT MAX(`recorded_at`) as `recorded_at`,
`player_id`,
GROUP_CONCAT(`gamertag` ORDER BY `recorded_at` DESC) as `gamertag`,
GROUP_CONCAT(`prefix` ORDER BY `recorded_at` DESC) as `prefix`,
GROUP_CONCAT(`city` ORDER BY `recorded_at` DESC) as `city`,
GROUP_CONCAT(`country` ORDER BY `recorded_at` DESC) as `country`,
GROUP_CONCAT(`state` ORDER BY `recorded_at` DESC) as `state`
FROM `player`
GROUP BY `player_id`) b
ON a.`player_id` = b.`player_id`
AND a.`recorded_at` = b.`recorded_at`;
SELECT *
FROM `ideal_player`;
查询#1
select *
from player a
JOIN (SELECT MAX(`recorded_at`) as `recorded_at`,
`player_id`,
GROUP_CONCAT(`gamertag` ORDER BY `recorded_at` DESC) as `gamertag`,
GROUP_CONCAT(`prefix` ORDER BY `recorded_at` DESC) as `prefix`,
GROUP_CONCAT(`city` ORDER BY `recorded_at` DESC) as `city`,
GROUP_CONCAT(`country` ORDER BY `recorded_at` DESC) as `country`,
GROUP_CONCAT(`state` ORDER BY `recorded_at` DESC) as `state`
FROM `player`
GROUP BY `player_id`) b
ON a.`player_id` = b.`player_id`
AND a.`recorded_at` = b.`recorded_at`;
| player_id | recorded_at | gamertag | prefix | city | country | state | recorded_at | player_id | gamertag | prefix | city | country | state |
| --------- | ----------- | -------- | ------ | -------- | ------------- | ----- | ----------- | --------- | ------------------------------------------- | ------ | ----------------- | --------------------------- | -------- |
| 4507 | 1533830400 | La Luna | | New York | United States | NY | 1533830400 | 4507 | La Luna,The Moon,The Moon | MVG | New York,Buffalo | United States,United States | NY,NY |
| 26640 | 1518278400 | Mimic | | | | | 1518278400 | 26640 | Mimic,Mimic,Mimic,Mimic,Wobbaduck,Wobbaduck | | Saskatoon,Toronto | Canada,Canada,Canada | SK,SK,ON |