SELECT查询使用来自另一行的数据

时间:2015-09-29 16:52:18

标签: sql postgresql window-functions

我有一个表格issue,结构如下:

+----+---------+-------------+------------+
| id | project | new_status  | updated_at |
+----+---------+-------------+------------+
| 1  | 1       | New         | 12:41:18   |
| 1  | 1       | In progress | 12:47:43   |
| 1  | 1       | Resolved    | 17:05:29   |
+----+---------+-------------+------------+

我需要实现一个查询,返回特定项目的每个问题在每个状态中花费的时间,如下所示:

+----+---------+-------------+------------+
| id | project | new_status  | time_diff  |
+----+---------+-------------+------------+
| 1  | 1       | New         | 00:06:25   |
| 1  | 1       | In progress | 04:17:46   |
+----+---------+-------------+------------+

我怎么能得到这个?最好不要使用special-concrete-db-features,即只使用纯SQL。但如果重要 - 我正在使用PostgreSQL。

4 个答案:

答案 0 :(得分:2)

我即时编写此查询,因此未经过测试:

SELECT id, project, new_status, (updated_at - nextUpdate) AS time_diff
                           --or CAST((updated_at - nextUpdate) AS time) AS time_diff
FROM (
    SELECT *, 
        LEAD(updated_at) OVER (PARTITION BY project ORDER BY updated_at) AS nextUpdate
    FROM yourTable) dt
WHERE nextUpdate IS NOT NULL;

相关答案为this

答案 1 :(得分:2)

如果缺少下一步,请假设当前时区的当前时间:

SELECT *
FROM  (
   SELECT *, lead(updated_at, 1, now()::time(0)) OVER (PARTITION BY id, project
                                                       ORDER BY updated_at)
           - updated_at AS time_diff
   FROM   issue
   ) sub
WHERE  new_status <> 'Resolved'  -- hide 'Resolved' row
ORDER  BY updated_at;

您的示例显示time值,这通常是一个有问题的选择。 (如果事件跨越多天会怎样?)请考虑timestamp or timestamptz

如果没有下一行或上一行,window functions lead() and lag()可以提供默认值。我使用没有小数秒的当前时间。

答案 2 :(得分:1)

可能是一个简单的第二个表,包含项目ID,步骤名称,开始时间和停止时间。对步骤进行排序的一些方法,例如简单的数字序列。然后在项目ID上运行两个表之间的连接,按步骤id排序,从结束时间中减去步骤的开始时间。使用case语句显示当前步骤没有结束时间.o

答案 3 :(得分:1)

由于你已经有一些使用lead()函数(肯定是数据库特定的)的例子,这里有一个不同的选项:http://sqlfiddle.com/#!15/497de/18

with t1 (id, project, new_status, updated_at, ndx) as (
  select id, project, new_status, updated_at,
  row_number() over (partition by id, project order by updated_at)
  from issue
)
,
t2 (id, project, new_status, starttime, endtime) as (
  select t1.id, t1.project, t1.new_status, t1.updated_at, t2.updated_at
  from t1
  left join t1 t2
  on t2.id = t1.id
  and t2.project = t1.project
  and t2.ndx = t1.ndx + 1
)
,
t3 (id, project, new_status, time_diff) as (
  select id, project, new_status, endtime - starttime
  from t2
)
select id, project, new_status, to_char(time_diff, 'HH24:MI:SS') as time_diff
from t3
where time_diff is not null

此选项使用公共表表达式为每个项目使用row_number()创建索引,然后根据该索引将表连接到自身;那是t2.ndx = t1.ndx + 1

从那里开始计算时间差并将其格式化以便显示。

如果您希望在“已解决”问题上看到该问题已经过了多长时间?如果coalesce(t2.updated_at,localtime)为空,则使用t2.updated_at之类的内容来获取当前时间。