我在使用PostgreSQL SELECT
时遇到了困难,起初看起来很简单。涉及的表:
CREATE TABLE events (id INT, customers_id INT);
CREATE TABLE jobs (
events_id INT,
"from" TIMESTAMP,
until TIMESTAMP,
users_id INT);
"from"
和最高until
定义我需要一个如下表:
events_id | customers_id | min(from) | max(until) | total_jobs | open_jobs
1 | 1 | .. 08:00 | .. 11:00 | 4 | 1
到目前为止,我的选择:
SELECT e.id, e.customers_id, min(j.from) as min_from, max(j.until) as max_until,
count(j.id) as total_jobs
FROM events e
LEFT JOIN jobs j ON j.events_id = e.id
GROUP BY e.id, e.customers_id
这为我提供了前5列的结果,但是如何只为users_id = NULL
的工作添加第二个计数呢?我以为我需要在作业表上再加上LEFT JOIN
,但是以某种方式我无法使其正常工作。
我如何正确有效地实现这一目标?
答案 0 :(得分:1)
假设open job
的定义为until
为空
WITH open_jobs_cte as (select events_id, customer_id, count(*) open_jobs FROM jobs WHERE until is null group by 1,2)
SELECT e.id, e.customers_id, min(j.from) as min_from, max(j.until) as max_until, count(j.id) as total_jobs, open_jobs
FROM events e
LEFT JOIN jobs j ON j.events_id = e.id
LEFT JOIN open_jobs_cte oj ON oj.events_id = e.id
GROUP BY e.id, e.customers_id
根据您的要求/设计,客户可以从cte中排除
答案 1 :(得分:1)
假设open_jobs是user_id为null的作业数?
Dic-swedish.xml
请注意SELECT e.id, e.customers_id, min(j.from) as min_from, max(j.until) as max_until,
count(j.id) as total_jobs,sum(case user_id is null then 1 else 0) as open_jobs
FROM events e
LEFT JOIN jobs j ON j.events_id = e.id
GROUP BY e.id, e.customers_id
。如果user_id为null,则您有一个空缺职位,因此您添加1,否则添加0。
sum(case user_id is null then 1 else 0)
由于还需要按min_from进行排序,因此可以
EDIT:
答案 2 :(得分:1)
在获取全部或大多数事件时,通常在联接之前聚集n表 最快(也是最简单):
SELECT e.id, e.customers_id
, j.min_from
, j.max_until
, j.total_jobs
, j.open_jobs
FROM events e
LEFT JOIN (
SELECT events_id AS id -- alias only to ease join syntax
, min("from") AS min_from
, max(until) AS max_until
, count(*) AS total_jobs
, count(*) FILTER (WHERE users_id IS NULL) AS open_jobs
-- equivalent for old versions:
-- , count(users_id IS NULL OR NULL) AS open_jobs
FROM jobs
GROUP BY 1
) j USING (id);
这样,您根本不需要GROUP BY
1张表。
由于您正在考虑第二个LEFT JOIN
:如果不首先进行汇总,则会遇到“代理交叉联接”的情况。
聚合FILTER
子句需要Postgres 9.4或更高版本。
相关:
此外:除非遇到复杂的情况,否则不要像from
那样使用reserved words作为列名...