Postgresql 基于输入为两行之间的行添加开始和结束日期的SQL查询

Postgresql 基于输入为两行之间的行添加开始和结束日期的SQL查询,postgresql,Postgresql,我有一个名为Acount的表,其结构如下 acc_id name value phase date 1 acc_type trial start t1 1 name1 value1 phase1 t2 1 acc_type trial end t3 1 name2 value2 phase2 t4

我有一个名为Acount的表,其结构如下

  acc_id      name       value   phase   date

    1         acc_type   trial   start    t1
    1         name1      value1  phase1   t2
    1         acc_type   trial   end      t3
    1         name2      value2  phase2   t4
    1         acc_type   trial   start    t5
    1         name3      value3  phase2   t6
    1         name4      value4  phase4   t7
    1         acc_type   trial   end      t8   
表是根据日期排序的

我想要的是添加两列
start\u date
end\u date
,并更新特定阶段值对的列
start和end
,其中
name
acc\u type
value
trial

因此,输出将如下所示:

acc_id      name       value   phase   date    start_date    end_date

    1         acc_type   trial   start    t1      t1          t3
    1         name1      value1  phase1   t2      t1          t3
    1         acc_type   trial   end      t3      t1          t3
    1         name2      value2  phase2   t4      
    1         acc_type   trial   start    t5      t5          t8 
    1         name3      value3  phase2   t6      t5          t8
    1         name4      value4  phase4   t7      t5          t8
    1         acc_type   trial   end      t8      t5          t8

我正在使用PostgreSQL。

这很复杂,因为需要按开始和结束进行分区。如果我假设正确的顺序是日期,那么您可以使用累积
max()

编辑:

我注意到“中间”有一些价值观。这需要更复杂的逻辑。其思想是计算开始和结束的净数量,并将其用于过滤:

select t.*,
       (case when netstartend > 0 or phase in ('start', 'end')
             then max(case when phase = 'start' then date end) over
                      (partition by acc_id order by date)
        end) as start_date,
       (case when netstartend > 0 or phase in ('start', 'end')
             then max(case when phase = 'end' then date end) over
                      (partition by acc_id order by date)
        end) as end_date
from (select t.*,
             sum(case when phase = 'start' then 1 when phase = 'end' then -1 else 0 end) over
                 (order by date) as netstartend
      from t
     ) t;

这很复杂,因为需要按开始和结束进行分区。如果我假设正确的顺序是日期,那么您可以使用累积
max()

编辑:

我注意到“中间”有一些价值观。这需要更复杂的逻辑。其思想是计算开始和结束的净数量,并将其用于过滤:

select t.*,
       (case when netstartend > 0 or phase in ('start', 'end')
             then max(case when phase = 'start' then date end) over
                      (partition by acc_id order by date)
        end) as start_date,
       (case when netstartend > 0 or phase in ('start', 'end')
             then max(case when phase = 'end' then date end) over
                      (partition by acc_id order by date)
        end) as end_date
from (select t.*,
             sum(case when phase = 'start' then 1 when phase = 'end' then -1 else 0 end) over
                 (order by date) as netstartend
      from t
     ) t;

你的acc_id相同吗?你的acc_id相同吗?结果并不像预期的那样。开始日期看起来不错,但结束日期没有按要求到来。谢谢您可以查看此链接“”我正在查看您编辑的答案。我会让你知道结果的。谢谢。以上评论是针对您的第一个解决方案。仍然没有达到预期的效果。开始日期很完美,但结束日期不正确。请你调查一下好吗。谢谢。@Rajeevkumar:您能为您遇到的问题提供一个解决方案吗?这总比让戈登做你所有的工作好。:-)@Gordon Linoff:这对我很有效。在结束日期的情况下,几乎不需要更改。我使用最小值代替最大值,并使用“按日期排序说明”。。然后它成功了。非常感谢您的查询。结果没有按预期出现。开始日期看起来不错,但结束日期没有按要求到来。谢谢您可以查看此链接“”我正在查看您编辑的答案。我会让你知道结果的。谢谢。以上评论是针对您的第一个解决方案。仍然没有达到预期的效果。开始日期很完美,但结束日期不正确。请你调查一下好吗。谢谢。@Rajeevkumar:您能为您遇到的问题提供一个解决方案吗?这总比让戈登做你所有的工作好。:-)@Gordon Linoff:这对我很有效。在结束日期的情况下,几乎不需要更改。我使用最小值代替最大值,并使用“按日期排序说明”。。然后它成功了。谢谢你的提问。