PostgreSQL查询包括WITH子查询

wil*_*map 5 sql postgresql greatest-n-per-group

从下表(已命名status)中,我需要提取状态为'01'2015年底的城镇代码.该列status_date存储城镇更改其状态的日期.

gid  | town      | status  | status_date
-----+-----------+---------+-------------
1    | 86001     | 00      | 2000-01-01
2    | 86001     | 01      | 2016-03-01
3    | 86002     | 01      | 2000-01-01
4    | 86003     | 00      | 2000-01-01
5    | 86003     | 01      | 2015-03-01
6    | 86003     | 02      | 2015-09-01
Run Code Online (Sandbox Code Playgroud)

我可以使用以下有点长的查询来实现这一点:

WITH tab AS (SELECT town, MAX(status_date) FROM status GROUP BY town)

  SELECT 
    t.town

  FROM tab t
    LEFT JOIN status s ON t.town = s.town AND t.max = s.status_date 

  WHERE t.max < '2016-01-01' AND s.status = '01' ; 
Run Code Online (Sandbox Code Playgroud)

结果是:

town   
-------
86002
Run Code Online (Sandbox Code Playgroud)

关于如何使这个查询更简单的任何想法?是WITH必不可少的?


要创建用于测试的表:

CREATE TABLE status (gid serial NOT NULL, town CHARACTER VARYING(5), status CHARACTER VARYING(2), status_date DATE) ;

INSERT INTO status (town, status, status_date) VALUES
  ('86001', '00', '2000-01-01'),
  ('86001', '01', '2016-03-01'),
  ('86002', '01', '2000-01-01'),
  ('86003', '00', '2000-01-01'),
  ('86003', '01', '2015-03-01'),
  ('86003', '02', '2015-09-01') ;
Run Code Online (Sandbox Code Playgroud)

Gor*_*off 3

您可以通过以下方式执行此操作distinct on

select s.*
from (select distinct on (s.town) s.*
      from status s
      where s.status_date < '2016-01-01'
      order by s.town, s.status_date desc
     ) s
where status = '01';
Run Code Online (Sandbox Code Playgroud)

此查询将获取每个城镇截至 2015 年底的最新状态。然后外部查询选择 的城镇01