重构 postgres join vs except
refactoring postgres join vs except
我正在尝试重构我的一个查询,但我做的事情并不正确。
我想合并两个查询并创建一个,但我对它如何与 LEFT JOIN 一起工作感到困惑。
All QuizMasters who have a state of "active"
减号(-)
QuizMasters who have an "active" event on a given day (not all QuizMasters have events only ~25%).
定义
- Events store
start_at
dow/wday for a given event, eg Monday-Sunday (albeit as a DateTime, only the wday and time are relevant).
- Events and QuizMasters have states which are either "active" or not.
旧查询(哪个数据正确)
SELECT first_name, last_name, email
FROM quiz_masters
WHERE quiz_masters.state = 'active' # (175 rows)
EXCEPT
SELECT first_name, last_name, email
FROM quiz_masters
LEFT JOIN events ON events.quiz_master_id = quiz_masters.id
WHERE quiz_masters.state = 'active'
AND EXTRACT(dow FROM events.start_at::timestamp::date) = 3 AND events.state = 'active'
GROUP BY first_name, last_name, email # (- 20 rows)
共有 155 行匹配查询。
组合查询无效
我想将它们组合成类似的东西:
SELECT first_name, last_name, email
FROM quiz_masters
LEFT JOIN events ON events.quiz_master_id = quiz_masters.id
WHERE quiz_masters.state = 'active'
AND events.quiz_master_id IS null
OR (EXTRACT(dow FROM events.start_at::timestamp::date) <> 3 AND events.state = 'active')
GROUP BY first_name, last_name, email
144 行(缺少 11 行)
但我不确定如何保留一些 quiz_masters
活跃但没有任何事件的所有行。它仍然删除它们。也许我需要其他类型的加入?
在第一个查询中,您排除了周三的所有活动事件,因此包括了任何一天的非活动事件。在组合查询中,您包括除星期三以外的任何一天都活跃的所有事件,并且没有任何非活跃事件。那是你的 11 行差异。
这应该让您回到 155 行:
SELECT DISTINCT first_name, last_name, email
FROM quiz_masters
LEFT JOIN (
SELECT quiz_master_id AS id, state
FROM events
WHERE EXTRACT(dow FROM events.start_at::timestamp) = 3
AND events.state = 'active') ev USING (id)
WHERE quiz_masters.state = 'active'
AND ev.state IS NULL;
显然您的测验大师有多个条目,但与其做 GROUP BY
,不如做 select DISTINCT
行。 GROUP BY
只能与聚合函数一起使用。
使用人类语言。
第一次查询:
Remove from quiz_masters
all entries who have the active events at the dow = 3
第二次查询:
Select entries from quiz_masters
who have active events at the dow <> 3
总的来说,没有平等的条件。例如,如果 quiz_masters 在 dow = 3 和 dow = 4 同时有活动事件,那么它将在第一个查询中不存在,但在第二个查询中出现。另一个例子:quiz_masters 根本没有事件。然后它将出现在第一个查询中,而在第二个查询中不存在。
大多数情况下,这种不便是因为 left (outer)
联接的错误用法:在 where
子句中使用左联接 table 将其转换为 (inner)
加入。如果 left join
正常工作 - 第一个查询将为空,第二个查询将 return 来自 quiz_masters 的所有活动条目独立于事件顺便说一句。
我正在尝试重构我的一个查询,但我做的事情并不正确。
我想合并两个查询并创建一个,但我对它如何与 LEFT JOIN 一起工作感到困惑。
All QuizMasters who have a state of "active"
减号(-)
QuizMasters who have an "active" event on a given day (not all QuizMasters have events only ~25%).
定义
- Events store
start_at
dow/wday for a given event, eg Monday-Sunday (albeit as a DateTime, only the wday and time are relevant).- Events and QuizMasters have states which are either "active" or not.
旧查询(哪个数据正确)
SELECT first_name, last_name, email
FROM quiz_masters
WHERE quiz_masters.state = 'active' # (175 rows)
EXCEPT
SELECT first_name, last_name, email
FROM quiz_masters
LEFT JOIN events ON events.quiz_master_id = quiz_masters.id
WHERE quiz_masters.state = 'active'
AND EXTRACT(dow FROM events.start_at::timestamp::date) = 3 AND events.state = 'active'
GROUP BY first_name, last_name, email # (- 20 rows)
共有 155 行匹配查询。
组合查询无效
我想将它们组合成类似的东西:
SELECT first_name, last_name, email
FROM quiz_masters
LEFT JOIN events ON events.quiz_master_id = quiz_masters.id
WHERE quiz_masters.state = 'active'
AND events.quiz_master_id IS null
OR (EXTRACT(dow FROM events.start_at::timestamp::date) <> 3 AND events.state = 'active')
GROUP BY first_name, last_name, email
144 行(缺少 11 行)
但我不确定如何保留一些 quiz_masters
活跃但没有任何事件的所有行。它仍然删除它们。也许我需要其他类型的加入?
在第一个查询中,您排除了周三的所有活动事件,因此包括了任何一天的非活动事件。在组合查询中,您包括除星期三以外的任何一天都活跃的所有事件,并且没有任何非活跃事件。那是你的 11 行差异。
这应该让您回到 155 行:
SELECT DISTINCT first_name, last_name, email
FROM quiz_masters
LEFT JOIN (
SELECT quiz_master_id AS id, state
FROM events
WHERE EXTRACT(dow FROM events.start_at::timestamp) = 3
AND events.state = 'active') ev USING (id)
WHERE quiz_masters.state = 'active'
AND ev.state IS NULL;
显然您的测验大师有多个条目,但与其做 GROUP BY
,不如做 select DISTINCT
行。 GROUP BY
只能与聚合函数一起使用。
使用人类语言。
第一次查询:
Remove from
quiz_masters
all entries who have the active events at thedow = 3
第二次查询:
Select entries from
quiz_masters
who have active events at thedow <> 3
总的来说,没有平等的条件。例如,如果 quiz_masters 在 dow = 3 和 dow = 4 同时有活动事件,那么它将在第一个查询中不存在,但在第二个查询中出现。另一个例子:quiz_masters 根本没有事件。然后它将出现在第一个查询中,而在第二个查询中不存在。
大多数情况下,这种不便是因为 left (outer)
联接的错误用法:在 where
子句中使用左联接 table 将其转换为 (inner)
加入。如果 left join
正常工作 - 第一个查询将为空,第二个查询将 return 来自 quiz_masters 的所有活动条目独立于事件顺便说一句。