我有一个具有以下结构的日志表:
CREATE TABLE mytable (
oid integer(10),
department integer(10),
cid integer(10),
status integer(1) comment 'statuses: 1-open, 2-accept, 3-done',
recordtime datetime
);
此表存储有关状态分配的一些数据。 oid - 组织,cid - card id。 当组织更新卡(设置新状态)在此表中插入行
时,组织会向部门发出警告我尝试从该表中选择统计数据,例如:按部门或按组织(oid)选择最大/最小接受时间,最大/最小完成时间和平均接受/完成时间。
here is sql fiddle of the example table and my query
问题是如何在按部门分组时选择列中的cid,oid和oid以及按部门分组时cid。换句话说:我想知道组织(oid)和卡ID(cid),例如,当我选择分组行时,最大接受时间
我需要这些列用于多个连接
UPD:
感谢 Roman Pekar ,他的回答让我走上了正确的道路。我使用他的第二个查询来编写我的最终查询。
首先:按部门分别选择平均接受/完成时间,最大/最小接受/完成时间,然后选择oid
和cid
以及每个部门的最长接受时间
with cte as (
select
oid, cid,
max(case when status=1 then recorddatetime end) as open,
max(case when status=2 then recorddatetime end) as accept,
max(case when status=3 then recorddatetime end) as done
from
mytable
group by oid, cid
having
max(case when status=1 then recorddatetime end) is not null and max(case when status=2 then recorddatetime end) is not null
and max(case when status=3 then recorddatetime end) is not null
order by oid, cid
)
select distinct on(department)
department, oid, cid,
ceil(extract(epoch from avg(cte.accept - cte.open) over (partition by department))) as avg_accept_time,
ceil(extract(epoch from avg(done - open) over (partition by department))) as avg_done_time,
ceil(extract(epoch from max(accept - open) over (partition by department))) as max_accept_time,
ceil(extract(epoch from max(done - open) over (partition by department))) as max_done_time,
ceil(extract(epoch from min(accept - open) over (partition by department))) as min_accept_time,
ceil(extract(epoch from min(done - open) over (partition by department))) as min_done_time
from cte cte
order by department, max_accept_time desc
第二:与第一个类似,但为组织选择所有这些值(oid
)
with cte as (
select
oid, cid,
max(case when status=1 then recorddatetime end) as open,
max(case when status=2 then recorddatetime end) as accept,
max(case when status=3 then recorddatetime end) as done
from
mytable
group by oid, cid
having
max(case when status=1 then recorddatetime end) is not null and max(case when status=2 then recorddatetime end) is not null
and max(case when status=3 then recorddatetime end) is not null
order by oid, cid
)
select distinct on(department, oid)
department, oid, cid,
ceil(extract(epoch from avg(cte.accept - cte.open) over (partition by department, oid))) as avg_accept_time,
ceil(extract(epoch from avg(done - open) over (partition by department, oid))) as avg_done_time,
ceil(extract(epoch from max(accept - open) over (partition by department, oid))) as max_accept_time,
ceil(extract(epoch from max(done - open) over (partition by department, oid))) as max_done_time,
ceil(extract(epoch from min(accept - open) over (partition by department, oid))) as min_accept_time,
ceil(extract(epoch from min(done - open) over (partition by department, oid))) as min_done_time
from cte cte
order by department, oid, max_accept_time desc
答案 0 :(得分:2)
不知道你要对你的查询做什么,但它确实过于复杂。您可以使用窗口函数和没有连接来简化第一次查询:
with cte as (
select
oid, department, cid,
max(case when status=1 then recordtime end) as open,
max(case when status=2 then recordtime end) as accept,
max(case when status=3 then recordtime end) as done
from mytable
group by oid, department, cid
)
select
department, oid,
extract(epoch from avg(accept - open)) as a_time,
extract(epoch from avg(done - open)) as d_time,
extract(epoch from max(accept - open)) as max_a_time,
extract(epoch from max(done - open)) as max_d_time
from cte
group by department, oid
order by department, oid;
<强> sql fiddle demo 强>
如果您希望从cid
获得max_time,则可以使用distinct on
语法:
with cte as (
select
oid, department, cid,
max(case when status=1 then recordtime end) as open,
max(case when status=2 then recordtime end) as accept,
max(case when status=3 then recordtime end) as done
from mytable
group by oid, department, cid
)
select distinct on (department, oid)
department, oid, cid,
extract(epoch from accept - open) as a_time
from cte
order by department, oid, accept - open desc;
或使用排名函数row_number():
with cte as (
select
oid, department, cid,
max(case when status=1 then recordtime end) as open,
max(case when status=2 then recordtime end) as accept,
max(case when status=3 then recordtime end) as done
from mytable
group by oid, department, cid
), cte2 as (
select
department, oid, cid,
accept, open,
row_number() over(
partition by department, oid
order by accept - open desc
) as rn
from cte
)
select
department, oid, cid,
extract(epoch from accept - open) as a_time
from cte2
where rn = 1
order by department, oid