2017-08-30 12 views
2

我使用的是Postgres 9.6。我的数据库包含属于用户的演示文稿。每个演示文稿都有很多幻灯片。每张幻灯片可以选择有背景图片。Postgres:加入匹配的第一个非空值?

Table "public.presentation" 
id    │ integer 
user_id  │ integer 

Table "public.slide" 
id    | integer 
presentation_id | integer (foreign key) 
index   | integer 

Table "public.background" 
slide_id .  | integer (foreign key) 
image_id  │ integer 

我想取回文稿的列表为特定的用户,并与名称和每个演示的ID一起,我想获得具有第一张幻灯片的背景图片的ID背景图像(如果没有任何幻灯片具有背景图像,则为null)。这样我可以在每个演示文稿旁边显示缩略图。

目前,我有一个查询来获取第一张幻灯片的背景图像ID仅在演示文稿:

SELECT presentation.*, background.image_id 
FROM presentation 
JOIN -- get the first slide in each presentation 
    (SELECT presentation_id FROM slide WHERE index=0) 
    ON slide.presentation_id=presentation.id 
LEFT OUTER JOIN -- join this with background (even if null) 
    background ON background.slide_id=slide.id 
WHERE presentation.user_id=100 
ORDER BY presentation.id; 

但我想改变这种获得的第一个非空的背景图片ID每次演示。不知道如何做到这一点!

我想知道Postgres的first_value可以帮助我吗?

回答

1
select * 
from 
    presentation 
    left join (
     select 
      b.image_id, s.presentation_id as id, 
      row_number() over (
       partition by s.presentation_id 
       order by s.index 
      ) as rn 
     from 
      slide s 
      inner join 
      background b on b.slide_id = s.id 
    ) b using (id) 
where rn = 1 or rn is null 
0

看起来像你只需要两列,让你错过的信息。

select slide.presentation_id, min(background.image_id) as background_image_id 
from slide 
left join background 
    on slide.id = background.slide_id 
group by slide.presentation_id 
order by slide.presentation_id, background_image_id; 

这给你每个演示文稿一行。

with first_background_image as (
    select slide.presentation_id, min(background.image_id) as background_image_id 
    from slide 
    left join background 
     on slide.id = background.slide_id 
    group by slide.presentation_id 
), first_slide as (
    select presentation_id, min(index) as first_slide_id 
    from slide 
    group by presentation_id 
) 
select fs.presentation_id, fs.first_slide_id, fbi.background_image_id 
from first_slide fs 
left join first_background_image fbi 
    on fbi.presentation_id = fs.presentation_id 
order by presentation_id; 

您应该包括CREATE TABLE和INSERT语句在你的问题。

create table presentation (
    id integer primary key, 
    user_id integer not null 
); 

create table slide (
    id integer primary key, 
    presentation_id integer not null 
     references presentation (id), 
    index integer not null, 
    unique (presentation_id, index) 
); 

create table background (
    -- Assumes one background per slide. 
    slide_id integer primary key 
     references slide (id), 
    image_id integer not null 
     -- references something? 
); 

insert into presentation values (1, 1), (2, 1), (3, 2); 
insert into slide values (1, 1, 1), (2, 1, 2), (3, 1, 3), (4, 2, 1), (5, 2, 2), (6, 3, 1); 
insert into background values (1, 3), (2, 7), (5, 18); 
相关问题