从玩家 ID 获取第一个和最后一个分数
Getting the first and last score from the Player ID
我正在尝试从中获取第一条和最后一条记录 table:
CREATE TABLE record(
id SERIAL PRIMARY KEY,
player_id BIGINT,
score INT
);
INSERT INTO record(player_id,score) VALUES(603,15);
INSERT INTO record(player_id,score) VALUES(603,5);
INSERT INTO record(player_id,score) VALUES(604,15);
INSERT INTO record(player_id,score) VALUES(604,10);
INSERT INTO record(player_id,score) VALUES(604,15);
INSERT INTO record(player_id,score) VALUES(612,20);
INSERT INTO record(player_id,score) VALUES(612,5);
INSERT INTO record(player_id,score) VALUES(612,10);
INSERT INTO record(player_id,score) VALUES(612,15);
如何获得 player_id
单行的第一个和最后一个分数?因此,table 将如下所示:
|==========|============|===============|
|player_id | first_score| last_score |
|==========|============|===============|
|603 | 15 | 5 |
|604 | 15 | 15 |
|612 | 20 | 15 |
|==========|============|===============|
这是我目前在 DB-Fiddle 中的内容,但我似乎无法正确理解:
我想我明白了...但是让我知道是否有更有效的方法来做到这一点:
SELECT
first_scores.player_id,
first_score,
last_score
FROM
(
SELECT
record.player_id,
record.id,
score AS first_score
FROM record
INNER JOIN (
SELECT
player_id,
MIN(record.id) AS min_record_id
FROM record
GROUP BY player_id
ORDER BY player_id
) AS min_scores
ON min_record_id = record.id
) AS first_scores
INNER JOIN
(
SELECT
record.player_id,
record.id,
score AS last_score
FROM record
INNER JOIN (
SELECT
player_id,
MAX(record.id) AS max_record_id
FROM record
GROUP BY player_id
ORDER BY player_id
) AS max_scores
ON max_record_id = record.id
) AS last_scores ON first_scores.player_id = last_scores.player_id
这是数据库 fiddle:
https://www.db-fiddle.com/f/gLuJ1dbwg5Eor3SUrubpbe/4
这是 Postgres 中的 greatest-n-per-group question which is typically done using distinct on ()
。
您需要一个查询来获取第一个分数,一个查询来获取最后一个分数(假设“第一个”和“最后一个”是通过 id
列定义的)
select fs.player_id,
fs.score as first_score,
ls.score as last_score
from (
-- "first" score per player
select distinct on (player_id) *
from record
order by player_id, id
) fs
left join (
-- "last" score per player
select distinct on (player_id) *
from record
order by player_id, id desc
) ls on ls.player_id = fs.player_id
order by player_id;
另一种选择(但可能效率较低)是使用 window function 对每个玩家的得分进行编号。然后使用过滤聚合将结果“透视”到两列中。
with numbered as (
select player_id,
row_number() over (partition by player_id order by id) as rn_first,
row_number() over (partition by player_id order by id desc) as rn_last,
score
from record
)
select player_id,
max(score) filter (where rn_first = 1) as first_score,
max(score) filter (where rn_last = 1) as last_score
from numbered
where rn_first = 1 or rn_last = 1
group by player_id
order by player_id;
我正在尝试从中获取第一条和最后一条记录 table:
CREATE TABLE record(
id SERIAL PRIMARY KEY,
player_id BIGINT,
score INT
);
INSERT INTO record(player_id,score) VALUES(603,15);
INSERT INTO record(player_id,score) VALUES(603,5);
INSERT INTO record(player_id,score) VALUES(604,15);
INSERT INTO record(player_id,score) VALUES(604,10);
INSERT INTO record(player_id,score) VALUES(604,15);
INSERT INTO record(player_id,score) VALUES(612,20);
INSERT INTO record(player_id,score) VALUES(612,5);
INSERT INTO record(player_id,score) VALUES(612,10);
INSERT INTO record(player_id,score) VALUES(612,15);
如何获得 player_id
单行的第一个和最后一个分数?因此,table 将如下所示:
|==========|============|===============|
|player_id | first_score| last_score |
|==========|============|===============|
|603 | 15 | 5 |
|604 | 15 | 15 |
|612 | 20 | 15 |
|==========|============|===============|
这是我目前在 DB-Fiddle 中的内容,但我似乎无法正确理解:
我想我明白了...但是让我知道是否有更有效的方法来做到这一点:
SELECT
first_scores.player_id,
first_score,
last_score
FROM
(
SELECT
record.player_id,
record.id,
score AS first_score
FROM record
INNER JOIN (
SELECT
player_id,
MIN(record.id) AS min_record_id
FROM record
GROUP BY player_id
ORDER BY player_id
) AS min_scores
ON min_record_id = record.id
) AS first_scores
INNER JOIN
(
SELECT
record.player_id,
record.id,
score AS last_score
FROM record
INNER JOIN (
SELECT
player_id,
MAX(record.id) AS max_record_id
FROM record
GROUP BY player_id
ORDER BY player_id
) AS max_scores
ON max_record_id = record.id
) AS last_scores ON first_scores.player_id = last_scores.player_id
这是数据库 fiddle: https://www.db-fiddle.com/f/gLuJ1dbwg5Eor3SUrubpbe/4
这是 Postgres 中的 greatest-n-per-group question which is typically done using distinct on ()
。
您需要一个查询来获取第一个分数,一个查询来获取最后一个分数(假设“第一个”和“最后一个”是通过 id
列定义的)
select fs.player_id,
fs.score as first_score,
ls.score as last_score
from (
-- "first" score per player
select distinct on (player_id) *
from record
order by player_id, id
) fs
left join (
-- "last" score per player
select distinct on (player_id) *
from record
order by player_id, id desc
) ls on ls.player_id = fs.player_id
order by player_id;
另一种选择(但可能效率较低)是使用 window function 对每个玩家的得分进行编号。然后使用过滤聚合将结果“透视”到两列中。
with numbered as (
select player_id,
row_number() over (partition by player_id order by id) as rn_first,
row_number() over (partition by player_id order by id desc) as rn_last,
score
from record
)
select player_id,
max(score) filter (where rn_first = 1) as first_score,
max(score) filter (where rn_last = 1) as last_score
from numbered
where rn_first = 1 or rn_last = 1
group by player_id
order by player_id;