Sql Postgres:使用第一个匹配的非空值联接?

Sql Postgres:使用第一个匹配的非空值联接?,sql,postgresql,Sql,Postgresql,我用的是Postgres9.6。我的数据库包含属于用户的演示文稿。每个演示文稿都有许多幻灯片。每张幻灯片都可以选择有背景图像 Table "public.presentation" id │ integer user_id │ integer Table "public.slide" id | integer presentation_id | integer (foreign key) index |

我用的是Postgres9.6。我的数据库包含属于用户的演示文稿。每个演示文稿都有许多幻灯片。每张幻灯片都可以选择有背景图像

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)。这样我就可以在每次演示的同时展示一个缩略图

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;
目前,我只需要查询演示文稿中第一张幻灯片的背景图像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是否能帮我什么忙?

看起来你只需要两列就可以得到你缺少的信息

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
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;

您应该在问题中包含CREATETABLE和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);