根据相关表中的最新值获取表中的条目

时间:2015-10-17 10:50:27

标签: sql postgresql sqlalchemy greatest-n-per-group

我在Postgresql中有一个微不足道的请求,但我无法破解它。

SQLFiddle:http://sqlfiddle.com/#!15/dc955/31

文件上传表:

id  file_name
1   file001
2   file002
3   file003
4   file004

文件状态表:

id  file_upload_id  file_status_id  status_date
1   1                1               October, 16 2015 19:22:51
2   1                2               October, 17 2015 09:19:20
3   1                3               October, 17 2015 09:20:51
4   1                4               October, 17 2015 09:22:51
5   2                1               October, 17 2015 13:45:10
6   3                1               October, 17 2015 09:22:57
7   1                1               October, 17 2015 23:22:12

配置文件状态:

id  status_code status_name
1   001          Unprocessed
2   002          Queued
3   003          Staging
4   004          Production

有三张桌子: file_upload < - > file_status < - >的 config_file_status 即可。 file_status 表保存文件在处理期间可以经历的各种状态

我需要的是获取file_upload.id, file_upload.file_name, file_status.file_status_id最新/最新file_status_id = 1的文件,即未处理的文件,这实际上是上传文件最初上传时创建的状态

到目前为止我已经尝试过了:

select file_upload.file_name, 
max(file_status.file_status_id) as latest_status
from file_upload, file_status, config_file_status
where file_upload.id = file_status.file_upload_id and
file_status.file_status_id = config_file_status.id 
Group By file_upload.file_name;

它不仅没有返回file001的正确最新状态,而且查询感觉像是过度杀戮。

正在寻找的是用于实现上述目的的正确SQL语法,但如果可以的话,也在SQLAlchemy Core中提供相同的语法。

使用Postgresql 9.3

3 个答案:

答案 0 :(得分:4)

您可以使用distinct on (s.file_upload_id)。将status_date desc放入order by以获取每个文件的最新上传日期。

select distinct on (s.file_upload_id) 
    s.file_upload_id, 
    u.file_name,
    s.file_status_id
from file_status s
join file_upload u on u.id = s.file_upload_id
where file_status_id = 1
order by file_upload_id, status_date desc;

SqlFiddle

如果仅在最新上传中搜索file_status_id,请移动查询外的where子句:

select *
from (
    select distinct on (s.file_upload_id) 
        s.file_upload_id, 
        u.file_name,
        s.file_status_id
    from file_status s
    join file_upload u on u.id = s.file_upload_id
    order by file_upload_id, status_date desc
    ) sub
where file_status_id = 2;

答案 1 :(得分:3)

通常使用window function

解决此类问题
select id, file_name, status_date, file_status_id
from (
  SELECT fu.id, 
         fu.file_name, 
         fs.status_date, 
         fs.file_status_id,
         row_number() over (partition by fu.id order by fs.status_date desc) as rn
  FROM file_upload fu
    LEFT JOIN file_status fs ON fu.id = fs.file_upload_id
) t
where rn = 1
  and file_status_id = 1
order by id, file_name;

答案 2 :(得分:1)

        select u.id, u.file_name, s.file_status_id, s.status_date 
        from 
        file_upload u, file_status s 
        where u.id = s.file_upload_id
        and 
        s.status_date = (select max(s.status_date) from file_status s 
        where u.id = s.file_upload_id) and s.file_status_id = 1

http://sqlfiddle.com/#!15/dc955/52