1

次の構造のログテーブルがあります。

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 - カード ID。このテーブルの組織更新カード (新しいステータスの設定) が行を挿入すると、組織は部門に属します

そのテーブルから統計データを選択しようとします。たとえば、部門別または組織別 (oid) の最大/最小受入時間、最大/最小完了時間、および平均受入/完了時間を選択します。

これは、テーブルの例と私のクエリのSQLフィドルです

問題は、部門ごとにグループ化するときに選択した列で cid を取得する方法、部門ごとにグループ化するときに oid と oid と cid を取得する方法です。つまり、グループ化された行を選択したときの最大受け入れ時間など、組織 (oid) とカード ID (cid) を知りたい

複数の結合のためにこれらの列が必要です

UPD: Roman Pekar
の おかげで、彼の答えは私を正しい道に導いてくれました。彼の 2 番目のクエリを使用して、最後のクエリを作成します。

最初に、部門ごとに平均受入/完了時間、最大/最小受入/完了時間を選択oidcid、各部門の最大受入時間を選択します。

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

2 番目: 1 番目と同様ですが、組織に対してこれらすべての値を選択します ( 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
4

1 に答える 1

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

cidmax_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

sql fiddle demo

于 2013-11-05T19:05:21.267 に答える