优化 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)