优化 PostgreSQL 查询 - 删除子查询
Optimizing PostgreSQL Query - Removing subquery
我有以下查询来获取特定列的值:level1
在开始时间和结束时间。我目前正在使用子查询来执行此操作,但我只想用一个 SELECT
查询来完成它。
SELECT
id,
(SELECT
b1.level1
FROM
table b1
WHERE
b1.id = b.id
and b1.start_time = MIN(b.start_time)) AS level1_at_start,
(SELECT
b1.level1
FROM
table b1
WHERE
b1.id = b.id
and b1.end_time = MAX(b.end_time)) AS level1_at_end
FROM
table b
GROUP BY b.id
;
SQL Fiddle link : link
示例输入和输出:
id level1 start_time end_time
-------------------------------------
i1 10 2 7
i1 50 5 10
i2 60 6 11
i2 20 1 6
i3 30 3 8
i3 40 4 9
id level1_at_start level1_at_end
----------------------------------------
i1 10 50
i2 20 60
i3 30 40
您可以使用 window functions 从(不同排序的)组中提取值:
CREATE TABLE ztable
( id text
, level integer
, start_time integer
, end_time integer
);
INSERT INTO ztable(id, level, start_time, end_time) VALUES
('i1', 10, 2, 7)
, ('i1', 50, 5, 10)
, ('i2', 60, 6, 11)
, ('i2', 20, 1, 6)
, ('i3', 30, 3, 8)
, ('i3', 40, 4, 9)
;
SELECT *
FROM (
SELECT id
, first_value(level) OVER (PARTITION BY id ORDER BY start_time ASC ) AS first_level
, first_value(level) OVER (PARTITION BY id ORDER BY end_time DESC) AS last_level
, row_number() OVER (PARTITION BY id ) AS rn
FROM ztable
) zzz
WHERE zzz.rn = 1
;
输出:
CREATE TABLE
INSERT 0 6
id | first_level | last_level | rn
----+-------------+------------+----
i1 | 10 | 50 | 1
i2 | 20 | 60 | 1
i3 | 30 | 40 | 1
(3 rows)
我有以下查询来获取特定列的值:level1
在开始时间和结束时间。我目前正在使用子查询来执行此操作,但我只想用一个 SELECT
查询来完成它。
SELECT
id,
(SELECT
b1.level1
FROM
table b1
WHERE
b1.id = b.id
and b1.start_time = MIN(b.start_time)) AS level1_at_start,
(SELECT
b1.level1
FROM
table b1
WHERE
b1.id = b.id
and b1.end_time = MAX(b.end_time)) AS level1_at_end
FROM
table b
GROUP BY b.id
;
SQL Fiddle link : link
示例输入和输出:
id level1 start_time end_time
-------------------------------------
i1 10 2 7
i1 50 5 10
i2 60 6 11
i2 20 1 6
i3 30 3 8
i3 40 4 9
id level1_at_start level1_at_end
----------------------------------------
i1 10 50
i2 20 60
i3 30 40
您可以使用 window functions 从(不同排序的)组中提取值:
CREATE TABLE ztable
( id text
, level integer
, start_time integer
, end_time integer
);
INSERT INTO ztable(id, level, start_time, end_time) VALUES
('i1', 10, 2, 7)
, ('i1', 50, 5, 10)
, ('i2', 60, 6, 11)
, ('i2', 20, 1, 6)
, ('i3', 30, 3, 8)
, ('i3', 40, 4, 9)
;
SELECT *
FROM (
SELECT id
, first_value(level) OVER (PARTITION BY id ORDER BY start_time ASC ) AS first_level
, first_value(level) OVER (PARTITION BY id ORDER BY end_time DESC) AS last_level
, row_number() OVER (PARTITION BY id ) AS rn
FROM ztable
) zzz
WHERE zzz.rn = 1
;
输出:
CREATE TABLE
INSERT 0 6
id | first_level | last_level | rn
----+-------------+------------+----
i1 | 10 | 50 | 1
i2 | 20 | 60 | 1
i3 | 30 | 40 | 1
(3 rows)