0

在 PostgreSQL 中,有issue表和子issue_step表 - 一个问题包含一个或多个步骤。

视图issue_v从问题和第一步和最后一步中拉出东西:author并且from_ts从第一步中拉出,而statusthru_ts从最后一步中拉出。

桌子

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

风景

create view seeplai.issue_v as
select isu.*,
      first.stp_ts as from_ts,
      first.author as author,
      first.notes as notes,
      last.stp_ts as thru_ts,
      last.status as status
from  seeplai.issue isu
join  seeplai.issue_step first on( first.isu_id = isu.isu_id and not exists(
      select 1 from seeplai.issue_step where isu_id=isu.isu_id and stp_id>first.stp_id ) )
join  seeplai.issue_step last on( last.isu_id = isu.isu_id and not exists(
        select 1 from seeplai.issue_step where isu_id=isu.isu_id and stp_id<last.stp_id    ) );

note1:issue_step.stp_id保证按时间顺序排列,所以使用它而不是stp_ts因为它已经被索引

这可行,但丑陋如罪,并且不能成为世界上最有效的查询。

4

2 回答 2

1

在此代码中,我使用子查询来查找第一步和最后一步 ID,然后使用找到的值连接到步表的两个实例。

SELECT  ISU.*
        ,S1.STP_TS AS FROM_TS
        ,S1.AUTHOR AS AUTHOR
        ,S1.NOTES AS NOTES
        ,S2.STP_TS AS THRU_TS
        ,S2.STATUS AS STATUS
FROM    SEEPLAI.ISSUE ISU
INNER JOIN
    (
    SELECT  ISU_ID
            ,MIN(STP_ID) AS MIN_ID
            ,MAX(STP_ID AS MAX_ID
    FROM    SEEPLAI.ISSUE_STEP
    GROUP BY
            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

注意:你真的不应该在视图中使用 select * 。在视图中明确列出您需要的所有字段是更好的做法

于 2013-05-14T03:47:36.507 回答
1

您是否考虑过使用窗口函数?

一个起点:

select steps.*,
       first_value(steps.stp_id) over w as first_id,
       last_value(steps.stp_id) over w as last_id
from issue_step steps
window w as (partition by steps.isu_id order by steps.stp_id)

顺便说一句,如果您事先知道 ID,最好在单独的查询中获取详细信息。(尝试一次性获取所有内容只会产生糟糕的计划,因为子查询或聚合上的连接,这将导致考虑/连接整个表的效率低下。)

于 2013-05-14T12:21:57.040 回答