クエリはおそらく次のように簡略化できます。
SELECT u.name AS user_name
, p.name AS project_name
, tl.created_on::date AS changeday
, coalesce(sum(nullif(new_value, '')::numeric), 0)
- coalesce(sum(nullif(old_value, '')::numeric), 0) AS hours
FROM users u
LEFT JOIN (
tasks t
JOIN fixins f ON f.id = t.fixin_id
JOIN projects p ON p.id = f.project_id
JOIN task_log_entries tl ON tl.task_id = t.id
AND tl.field_id = 18
AND (tl.created_on IS NULL OR
tl.created_on >= '2013-09-08' AND
tl.created_on < '2013-09-09') -- upper border!
) ON t.assignee_id = u.id
WHERE EXISTS (SELECT 1 FROM tasks t1 WHERE t1.assignee_id = u.id)
GROUP BY 1, 2, 3
ORDER BY 1, 2, 3;
これにより、これまでにタスクを実行したことがあるすべてのユーザーが返されます。
プロジェクトごとおよび1日あたりのデータに加えて task_log_entries
で指定された日付範囲にデータが存在する場合 。
主なポイント
-
集計関数
sum()
NULL
を無視します 値。COALESCE()
行ごと 2つの合計の差として計算を再キャストするとすぐに、もう必要ありません:,coalesce(sum(nullif(new_value, '')::numeric), 0) - coalesce(sum(nullif(old_value, '')::numeric), 0) AS hours
ただし、 if すべて 選択範囲の列に
NULL
があります または空の文字列、合計をCOALESCE
にラップします 一度。
私はnumeric
を使用していますfloat
の代わりに 、丸め誤差を最小限に抑えるためのより安全な代替手段。 -
users
の結合から明確な値を取得しようとする試み およびtasks
task
に参加するので、無駄です もう一度下に。クエリ全体をフラット化して、クエリをよりシンプルかつ高速にします。 -
これらの
位置参照 単なる表記上の便宜です: GROUP BY 1, 2, 3 ORDER BY 1, 2, 3
...元のクエリと同じことを行います。
-
date
を取得するにはtimestamp
からdate
にキャストするだけです :tl.created_on::date AS changeday
ただし、
WHERE
の元の値でテストすることをお勧めします。 句またはJOIN
条件(可能な場合、ここで可能)、Postgresは列にプレーンインデックスを使用できます(可能な場合):AND (tl.created_on IS NULL OR tl.created_on >= '2013-09-08' AND tl.created_on < '2013-09-09') -- next day as excluded upper border
日付リテラルに注意してください
timestamp
に変換されます00:00
に 今日の現在の時刻ゾーン 。 次へを選択する必要があります 日と除外 それを上縁として。または、 '2013-09-22 0:0 +2':: timestamptz
のようなより明示的なタイムスタンプリテラルを指定します 。上部境界線の除外の詳細: -
要件
every user who has ever been assigned to a task
WHERE
を追加します 条項:WHERE EXISTS (SELECT 1 FROM tasks t1 WHERE t1.assignee_id = u.id)
-
最も重要なこと :
LEFT [OUTER] JOIN
結合の左側にあるすべての行を保持します。WHERE
を追加する 権利の条項 テーブルはこの効果を無効にすることができます。代わりに、フィルター式をJOIN
に移動します 条項。 詳細はこちら: -
括弧 テーブルが結合される順序を強制するために使用できます。単純なクエリではめったに必要ありませんが、この場合は非常に便利です。この機能を使用して
task
に参加します 、fixins
、projects
およびtask_log_entries
左に移動する前に-すべてをusers
に参加させます -サブクエリなし。 -
テーブルエイリアス 複雑なクエリを簡単に作成できます。