如何在引用 table 的列中查询具有最大值的行?
How to query row with max value in a column in a referencing table?
有一些流行的情况,需要从 table 中 select 具有最大值(或最小值或其他聚合函数结果)的行。我的情况更复杂 - 它在图片中添加了 JOIN
。
这是一个例子:
CREATE TABLE spacecraft (
id serial PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE launch (
id serial PRIMARY KEY,
spacecraft_id int REFERENCES spacecraft(id) NOT NULL,
started timestamptz NOT NULL,
success bool NOT NULL
);
INSERT INTO spacecraft (id, name) VALUES
(1, 'Bebop'),
(2, 'Serenity'),
(3, 'Death Start');
INSERT INTO launch (spacecraft_id, started, success) VALUES
(1, 'January 8 04:05:06 2999 UTC', true),
(2, 'December 1 01:00:00 3432 UTC', true),
(3, 'February 15 00:00:00 4521 UTC', false),
(3, 'July 10 12:05:00 4525 UTC', true);
http://sqlfiddle.com/#!15/a1921
如何select每个航天器的最后发射结果(launch.success)?
更新 #1
这是我目前的解决方案:
SELECT DISTINCT S.*, last_launch, L2.success FROM spacecraft AS S
LEFT OUTER JOIN (SELECT *, MAX(started) OVER (PARTITION BY spacecraft_id) AS last_launch FROM launch) AS L1
ON L1.spacecraft_id=S.id
LEFT OUTER JOIN launch AS L2
ON L2.started=L1.last_launch;
如果你只想获得最大的成功,那么你已经添加了一个条件来过滤只有成功。并像您一样使用 Window Functions:
select spacecraft.* , max(started) over (partition by spacecraft.id)
from spacecraft
left outer join
launch
on spacecraft.id = spacecraft_id
where success
这是我的解决方案。
SELECT s.id, s.name, l.last_started
FROM spacecraft AS s
INNER JOIN (SELECT spacecraft_id, MAX(started) AS last_started FROM launch WHERE success GROUP BY spacecraft_id) AS l
ON s.id = l.spacecraft_id
假设您想要结果中 spacecraft
的所有列,加上最新的 launch
和同一行的 success
。
每个航天器的几次发射速度更快:
SELECT s.*, l.last_launch, l.success
FROM spacecraft s
LEFT JOIN (
SELECT DISTINCT ON (spacecraft_id)
spacecraft_id, started AS last_launch, success
FROM launch
ORDER BY spacecraft_id, started DESC
) l ON l.spacecraft_id = s.id;
每个航天器的多次发射速度更快:
SELECT s.*, l.last_launch, l.success
FROM spacecraft s
LEFT JOIN LATERAL (
SELECT started AS last_launch, success
FROM launch
WHERE spacecraft_id = s.id
ORDER BY started DESC
LIMIT 1
) l ON true;
LATERAL
需要 Postgres 9.3+。
LEFT JOIN
包括没有发射的航天器。否则使用 JOIN
.
快速 中任一查询的基本要素是 (spacecraft_id, started)
上的多列索引。对于这个特定的查询,success
到索引以允许仅索引扫描将是有益的:
CREATE INDEX launch_foo_idx ON launch (spacecraft_id, started DESC, success);
详细解释:
- Optimize GROUP BY query to retrieve latest record per user
- Select first row in each GROUP BY group?
有一些流行的情况,需要从 table 中 select 具有最大值(或最小值或其他聚合函数结果)的行。我的情况更复杂 - 它在图片中添加了 JOIN
。
这是一个例子:
CREATE TABLE spacecraft (
id serial PRIMARY KEY,
name text NOT NULL
);
CREATE TABLE launch (
id serial PRIMARY KEY,
spacecraft_id int REFERENCES spacecraft(id) NOT NULL,
started timestamptz NOT NULL,
success bool NOT NULL
);
INSERT INTO spacecraft (id, name) VALUES
(1, 'Bebop'),
(2, 'Serenity'),
(3, 'Death Start');
INSERT INTO launch (spacecraft_id, started, success) VALUES
(1, 'January 8 04:05:06 2999 UTC', true),
(2, 'December 1 01:00:00 3432 UTC', true),
(3, 'February 15 00:00:00 4521 UTC', false),
(3, 'July 10 12:05:00 4525 UTC', true);
http://sqlfiddle.com/#!15/a1921
如何select每个航天器的最后发射结果(launch.success)?
更新 #1
这是我目前的解决方案:
SELECT DISTINCT S.*, last_launch, L2.success FROM spacecraft AS S
LEFT OUTER JOIN (SELECT *, MAX(started) OVER (PARTITION BY spacecraft_id) AS last_launch FROM launch) AS L1
ON L1.spacecraft_id=S.id
LEFT OUTER JOIN launch AS L2
ON L2.started=L1.last_launch;
如果你只想获得最大的成功,那么你已经添加了一个条件来过滤只有成功。并像您一样使用 Window Functions:
select spacecraft.* , max(started) over (partition by spacecraft.id)
from spacecraft
left outer join
launch
on spacecraft.id = spacecraft_id
where success
这是我的解决方案。
SELECT s.id, s.name, l.last_started
FROM spacecraft AS s
INNER JOIN (SELECT spacecraft_id, MAX(started) AS last_started FROM launch WHERE success GROUP BY spacecraft_id) AS l
ON s.id = l.spacecraft_id
假设您想要结果中 spacecraft
的所有列,加上最新的 launch
和同一行的 success
。
每个航天器的几次发射速度更快:
SELECT s.*, l.last_launch, l.success
FROM spacecraft s
LEFT JOIN (
SELECT DISTINCT ON (spacecraft_id)
spacecraft_id, started AS last_launch, success
FROM launch
ORDER BY spacecraft_id, started DESC
) l ON l.spacecraft_id = s.id;
每个航天器的多次发射速度更快:
SELECT s.*, l.last_launch, l.success
FROM spacecraft s
LEFT JOIN LATERAL (
SELECT started AS last_launch, success
FROM launch
WHERE spacecraft_id = s.id
ORDER BY started DESC
LIMIT 1
) l ON true;
LATERAL
需要 Postgres 9.3+。
LEFT JOIN
包括没有发射的航天器。否则使用 JOIN
.
快速 中任一查询的基本要素是 (spacecraft_id, started)
上的多列索引。对于这个特定的查询,success
到索引以允许仅索引扫描将是有益的:
CREATE INDEX launch_foo_idx ON launch (spacecraft_id, started DESC, success);
详细解释:
- Optimize GROUP BY query to retrieve latest record per user
- Select first row in each GROUP BY group?