2016-10-11 5 views
0

私のpostgresクエリの1つに奇妙な問題があります。非常に特定の1つのシナリオを除いて、さまざまな他のグループ、合計などを含む複数のシナリオでクエリが正常に動作します。Postgres:ケースとグループの使用時に集計関数が必要ですが、結合が使用されている場合のみ

以下のコードは、5つの異なるテーブルの行数をカウントしています(それ自体がダムであるという事実を無視し、非常に厄介なデータベース構造です)、CASE関数で返される値に応じてグループ化します。それは以下の通りであるとき、正常に動作します:

SELECT SUM(count) as count, status FROM 
(SELECT count(fsp.id) as count, CASE WHEN fsp.stageonecompletetime = 0 THEN 'in-progress' 
WHEN fsp.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
WHEN fsp.completedtime = 0 THEN 'awaiting-authorisation' 
WHEN fsp.senttodate = 0 THEN 'awaiting-distribution' 
WHEN fsp.senttodate > 0 AND superseded = 0 THEN 'completed' 
ELSE 'archived' END AS status FROM fleet_documents.fleet_solution_policy fsp WHERE TO_TIMESTAMP(fsp.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(fsp.createdtime) < '2016-10-03' GROUP BY status 
UNION ALL 
SELECT count(cba.id) as count, CASE WHEN cba.stageonecompletetime = 0 THEN 'in-progress' 
WHEN cba.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
WHEN cba.completedtime = 0 THEN 'awaiting-authorisation' 
WHEN cba.senttodate = 0 THEN 'awaiting-distribution' 
WHEN cba.senttodate > 0 AND superseded = 0 THEN 'completed' 
ELSE 'archived' END AS status FROM fleet_documents.casing_buyback_agreement cba WHERE TO_TIMESTAMP(cba.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(cba.createdtime) < '2016-10-03' GROUP BY status 
UNION ALL 
SELECT count(ftp.id) as count, CASE WHEN ftp.stageonecompletetime = 0 THEN 'in-progress' 
WHEN ftp.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
WHEN ftp.completedtime = 0 THEN 'awaiting-authorisation' 
WHEN ftp.senttodate = 0 THEN 'awaiting-distribution' 
WHEN ftp.senttodate > 0 AND superseded = 0 THEN 'completed' 
ELSE 'archived' END AS status FROM fleet_documents.fleet_tyre_policy ftp WHERE TO_TIMESTAMP(ftp.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(ftp.createdtime) < '2016-10-03' GROUP BY status 
UNION ALL 
SELECT count(ds.id) as count, CASE WHEN ds.stageonecompletetime = 0 THEN 'in-progress' 
WHEN ds.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
WHEN ds.completedtime = 0 THEN 'awaiting-authorisation' 
WHEN ds.senttodate = 0 THEN 'awaiting-distribution' 
WHEN ds.senttodate > 0 AND superseded = 0 THEN 'completed' 
ELSE 'archived' END AS status FROM fleet_documents.dealer_sla ds WHERE TO_TIMESTAMP(ds.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(ds.createdtime) < '2016-10-03' GROUP BY status 
UNION ALL 
SELECT count(cg.id) as count, CASE WHEN cg.stageonecompletetime = 0 THEN 'in-progress' 
WHEN cg.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
WHEN cg.completedtime = 0 THEN 'awaiting-authorisation' 
WHEN cg.senttodate = 0 THEN 'awaiting-distribution' 
WHEN cg.senttodate > 0 AND superseded = 0 THEN 'completed' 
ELSE 'archived' END AS status FROM fleet_documents.casing_grid cg WHERE TO_TIMESTAMP(cg.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(cg.createdtime) < '2016-10-03' GROUP BY status) allDocuments 
GROUP BY status 

しかし、私がしなければならないとき、私は迷惑なエラーを取得し、以下のように、私はユーザーによって結果をフィルタリングできるようにするために、クエリに参加する:

SELECT SUM(count) as count, status FROM 
    (SELECT count(fsp.id) as count, CASE WHEN fsp.stageonecompletetime = 0 THEN 'in-progress' 
     WHEN fsp.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
     WHEN fsp.completedtime = 0 THEN 'awaiting-authorisation' 
     WHEN fsp.senttodate = 0 THEN 'awaiting-distribution' 
     WHEN fsp.senttodate > 0 AND superseded = 0 THEN 'completed' 
     ELSE 'archived' END AS status FROM fleet_documents.fleet_solution_policy fsp JOIN users u1 ON u1.id = fsp.user_id WHERE TO_TIMESTAMP(fsp.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(fsp.createdtime) < '2016-10-03' AND lower(u1.username) = 'Test' GROUP BY status 
    UNION ALL 
    SELECT count(cba.id) as count, CASE WHEN cba.stageonecompletetime = 0 THEN 'in-progress' 
     WHEN cba.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
     WHEN cba.completedtime = 0 THEN 'awaiting-authorisation' 
     WHEN cba.senttodate = 0 THEN 'awaiting-distribution' 
     WHEN cba.senttodate > 0 AND superseded = 0 THEN 'completed' 
     ELSE 'archived' END AS status FROM fleet_documents.casing_buyback_agreement cba JOIN users u4 ON u4.id = cba.user_id WHERE TO_TIMESTAMP(cba.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(cba.createdtime) < '2016-10-03' AND lower(u4.username) = 'Test' GROUP BY status 
    UNION ALL 
    SELECT count(ftp.id) as count, CASE WHEN ftp.stageonecompletetime = 0 THEN 'in-progress' 
     WHEN ftp.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
     WHEN ftp.completedtime = 0 THEN 'awaiting-authorisation' 
     WHEN ftp.senttodate = 0 THEN 'awaiting-distribution' 
     WHEN ftp.senttodate > 0 AND superseded = 0 THEN 'completed' 
     ELSE 'archived' END AS status FROM fleet_documents.fleet_tyre_policy ftp JOIN users u2 ON u2.id = ftp.user_id WHERE TO_TIMESTAMP(ftp.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(ftp.createdtime) < '2016-10-03' AND lower(u2.username) = 'Test' GROUP BY status 
    UNION ALL 
    SELECT count(ds.id) as count, CASE WHEN ds.stageonecompletetime = 0 THEN 'in-progress' 
     WHEN ds.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
     WHEN ds.completedtime = 0 THEN 'awaiting-authorisation' 
     WHEN ds.senttodate = 0 THEN 'awaiting-distribution' 
     WHEN ds.senttodate > 0 AND superseded = 0 THEN 'completed' 
     ELSE 'archived' END AS status FROM fleet_documents.dealer_sla ds JOIN users u3 ON u3.id = ds.user_id WHERE TO_TIMESTAMP(ds.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(ds.createdtime) < '2016-10-03' AND lower(u3.username) = 'Test' GROUP BY status 
    UNION ALL 
    SELECT count(cg.id) as count, CASE WHEN cg.stageonecompletetime = 0 THEN 'in-progress' 
     WHEN cg.stagetwocompletetime = 0 THEN 'awaiting-final-review' 
     WHEN cg.completedtime = 0 THEN 'awaiting-authorisation' 
     WHEN cg.senttodate = 0 THEN 'awaiting-distribution' 
     WHEN cg.senttodate > 0 AND superseded = 0 THEN 'completed' 
     ELSE 'archived' END AS status FROM fleet_documents.casing_grid cg JOIN users u5 ON u5.id = cg.user_id WHERE TO_TIMESTAMP(cg.createdtime) >= '2016-09-03' AND TO_TIMESTAMP(cg.createdtime) < '2016-10-03' AND lower(u5.username) = 'Test' GROUP BY status) allDocuments 
GROUP BY status 

エラーは次のとおりです。エラー:列 "fsp.stageonecompletetime"は、GROUP BY句に表示するか、集計関数で使用する必要があります。

ここで、私はなぜ私がユーザーテーブルとの結合を行うときにのみ、このエラーが返されるのか理解できません。

ご協力いただければ幸いです。

+1

私はOracle SQL環境で作業しているので役立つかどうかはわかりませんが、そこにはステータスをグループに入れることはできません。ケース全体をパースする必要があります。あなたはそれを試しましたか? –

+0

ここで 'TO_TIMESTAMP'が何をしているのか説明できますか? createdtimeは文字列として格納されていますか?もしそうなら、どんな形式ですか?そして、 'lower(username)= 'テスト'は面白く見えませんか? –

+0

ねえ、確かに、 'テスト'は私の間違いでした(私はこの質問を提出するときに実際のユーザ名を変更したので)、それは低いと忘れました。 – bigad1992

答えて

1

あなたのユーザーテーブルにstatusという名前の列があると思われ、エイリアスケース式を参照しないようにグループのセマンティクスが変更されました。

使用しているエイリアスを変更してみてください。

+0

ありがとう、私はユーザーテーブルにステータス列を持っているので、これが問題になっている可能性があります。私は結局のところ、サブクエリ内の集計関数とグループ化を取り出し、すべての行をそのまま返してから、メインクエリでのみ集計とグループ化を行うことで、異なる方法で修正しました。 – bigad1992

+0

@ David Alldridge:これはおそらくそうです。また、これは 'GROUP BY'でエイリアスを使用しない方が良いことを示しています。なぜなら、' status'の代わりに 'state'エイリアスを使用すると、誰も' state'カラムを1つに追加しない限りエイリアスを使用する場合は、エイリアスとカラムの名前が同じにならないように、いくつかの命名規則を使用する必要があります。 –

+0

@ bigad1992:いいですね。同じテーブルをすべて使用している場合、単純にすべてのテーブルを結合して全体を処理できます。 –

1

これは実際の回答ではありません。正解はすでにDavid Aldridgeによって与えられています。


ここではどのようにクエリを記述しますか。私はユーザーにまったく参加しません。そして、私は最初にすべてのテーブルを接着して、あたかもそれらがただ一つのテーブルであるかのように扱います。サブクエリ内のデータを分類し、メインクエリで作成したエイリアスを使用します。

select count(*), status 
from 
(
    select 
    case 
     when stageonecompletetime = 0 then 'in-progress' 
     when stagetwocompletetime = 0 then 'awaiting-final-review' 
     when completedtime = 0 then 'awaiting-authorisation' 
     when senttodate = 0 then 'awaiting-distribution' 
     when senttodate > 0 and superseded = 0 then 'completed' 
     else 'archived' 
    end as status 
    from 
    (
    select user_id, createdtime, stageonecompletetime, stagetwocompletetime, completedtime, senttodate, superseded from fleet_documents.fleet_solution_policy 
    union all 
    select user_id, createdtime, stageonecompletetime, stagetwocompletetime, completedtime, senttodate, superseded from fleet_documents.casing_buyback_agreement 
    union all 
    select user_id, createdtime, stageonecompletetime, stagetwocompletetime, completedtime, senttodate, superseded from fleet_documents.fleet_tyre_policy 
    union all 
    select user_id, createdtime, stageonecompletetime, stagetwocompletetime, completedtime, senttodate, superseded from fleet_documents.dealer_sla 
    union all 
    select user_id, createdtime, stageonecompletetime, stagetwocompletetime, completedtime, senttodate, superseded from fleet_documents.casing_grid 
) data 
) classified 
where createdtime >= '2016-09-03' 
    and createdtime < '2016-10-03' 
    and user_id in (select id from users where lower(username) = 'test') 
group by status 
order by count(*); 

遅すぎる場合は、WHERE句を単一のテーブルクエリに移動します。そうであるように、クエリははるかに読みやすくメンテナンス可能です。

関連する問題