postgresql - in SQL, best way to join first and last instance of child table without NOT EXISTS? -
in postgresql, have issue
table , child issue_step
table - issue contains 1 or more steps.
the view issue_v
pulls things issue , first , last step: author
, from_ts
pulled first step, while status
, thru_ts
pulled last step.
the tables
create table if not exists seeplai.issue( isu_id serial primary key, subject varchar(240) ); create table if not exists seeplai.issue_step( stp_id serial primary key, isu_id int not null references seeplai.issue on delete cascade, status varchar(12) default 'open', stp_ts timestamp(0) default current_timestamp, author varchar(40), notes text );
the view
create view seeplai.issue_v select isu.*, first.stp_ts from_ts, first.author author, first.notes notes, last.stp_ts thru_ts, last.status status seeplai.issue isu join seeplai.issue_step first on( first.isu_id = isu.isu_id , not exists( select 1 seeplai.issue_step isu_id=isu.isu_id , stp_id>first.stp_id ) ) join seeplai.issue_step last on( last.isu_id = isu.isu_id , not exists( select 1 seeplai.issue_step isu_id=isu.isu_id , stp_id<last.stp_id ) );
note1: issue_step.stp_id
guaranteed chronologically sequential, using instead of stp_ts
because it's indexed
this works, ugly sin, , cannot efficient query in world.
in code, use sub-query find first , last step ids, , join 2 instances of step table using found values.
select isu.* ,s1.stp_ts from_ts ,s1.author author ,s1.notes notes ,s2.stp_ts thru_ts ,s2.status status seeplai.issue isu inner join ( select isu_id ,min(stp_id) min_id ,max(stp_id max_id seeplai.issue_step group isu_id ) sq on sq.isu_id = isu.isu.id inner join seeplai.issue_step s1 on s1.stp_id = sq.min_id inner join seeplai.issue_step s2 on s2.stp_id = sq.max_id
note: shouldn't using select * in view. better practice list out fields need in view explicitly
Comments
Post a Comment