两个 SQL 表中的任何一个都有值
Either of two SQL tables have a value
我有两个 table,task_list_sharee
和 task_list_assignee
。他们都引用了 task_list
table.
还有一个 task
table 引用了 task_list
table 因为 task
总是存在于 task_list
中.
给定一个 task
,我想知道 task_list_sharee
或 task_list_assignee
是否有值。现在我将其作为两个 SQL 语句来执行,如下所示:
SELECT count(*)
FROM task_list_assignee a
INNER JOIN task_list l ON l.uid = a.task_list_uid
INNER JOIN task t ON t.task_list_uid = l.uid
WHERE t.uid = ?
SELECT count(*)
FROM task_list_sharee s
INNER JOIN task_list l ON l.uid = s.task_list_uid
INNER JOIN task t ON t.task_list_uid = l.uid
WHERE t.uid = ?
如果其中一个非零,我就下注。我认为这必须作为一个单一的 SQL 语句来实现,但我有点难过。
如果您以 Task 作为基础 table 并进行一系列左连接,您应该能够通过 coalesce 确定哪些任务对 assignee 和 sharee 都有价值:
select count(*)
from task as t
left join
task_list as l
on t.task_list_uid = l.uid
left join
task_list_assignee as a
on l.uid = a.task_list_uid
left join
task_list_sharee as s
on l.uid = s.task_list_uid
where coalesce( a.task_list_uid, s.task_list_uid ) is not null
and t.uid = ?
SQL Fiddle here
多个连接的完整计数性能(对于 LEFT JOIN
更是如此)可能会迅速恶化。虽然您只需要证明单行的存在,但没有必要这样做。使用 EXISTS
- 名副其实 - 允许最佳查询计划:
SELECT EXISTS (
SELECT 1
FROM task t
WHERE t.uid = ? -- provide uid here
AND (
EXISTS (
SELECT 1
FROM task_list_assignee
WHERE task_list_uid = t.task_list_uid
)
OR EXISTS (
SELECT 1
FROM task_list_sharee
WHERE task_list_uid = t.task_list_uid
)
)
);
应该大大比完整计数快。
我也去掉了中间人。加入 task_list
只会确定 task_list
中的相关行存在 - 这是浪费时间,因为:
a task
always exists within a task_list
.
理想情况下使用 FK 约束实现以强制参照完整性。
在没有实际 table 定义的情况下,我的有根据的猜测将不得不做。
要使任何 table 大小的 快速 ,您需要
上的 3 个 btree(默认)索引
task(uid, task_list_uid)
task_list_assignee(task_list_uid)
task_list_sharee(task_list_uid)
我有两个 table,task_list_sharee
和 task_list_assignee
。他们都引用了 task_list
table.
还有一个 task
table 引用了 task_list
table 因为 task
总是存在于 task_list
中.
给定一个 task
,我想知道 task_list_sharee
或 task_list_assignee
是否有值。现在我将其作为两个 SQL 语句来执行,如下所示:
SELECT count(*)
FROM task_list_assignee a
INNER JOIN task_list l ON l.uid = a.task_list_uid
INNER JOIN task t ON t.task_list_uid = l.uid
WHERE t.uid = ?
SELECT count(*)
FROM task_list_sharee s
INNER JOIN task_list l ON l.uid = s.task_list_uid
INNER JOIN task t ON t.task_list_uid = l.uid
WHERE t.uid = ?
如果其中一个非零,我就下注。我认为这必须作为一个单一的 SQL 语句来实现,但我有点难过。
如果您以 Task 作为基础 table 并进行一系列左连接,您应该能够通过 coalesce 确定哪些任务对 assignee 和 sharee 都有价值:
select count(*)
from task as t
left join
task_list as l
on t.task_list_uid = l.uid
left join
task_list_assignee as a
on l.uid = a.task_list_uid
left join
task_list_sharee as s
on l.uid = s.task_list_uid
where coalesce( a.task_list_uid, s.task_list_uid ) is not null
and t.uid = ?
SQL Fiddle here
多个连接的完整计数性能(对于 LEFT JOIN
更是如此)可能会迅速恶化。虽然您只需要证明单行的存在,但没有必要这样做。使用 EXISTS
- 名副其实 - 允许最佳查询计划:
SELECT EXISTS (
SELECT 1
FROM task t
WHERE t.uid = ? -- provide uid here
AND (
EXISTS (
SELECT 1
FROM task_list_assignee
WHERE task_list_uid = t.task_list_uid
)
OR EXISTS (
SELECT 1
FROM task_list_sharee
WHERE task_list_uid = t.task_list_uid
)
)
);
应该大大比完整计数快。
我也去掉了中间人。加入 task_list
只会确定 task_list
中的相关行存在 - 这是浪费时间,因为:
a
task
always exists within atask_list
.
理想情况下使用 FK 约束实现以强制参照完整性。 在没有实际 table 定义的情况下,我的有根据的猜测将不得不做。
要使任何 table 大小的 快速 ,您需要
上的 3 个 btree(默认)索引task(uid, task_list_uid)
task_list_assignee(task_list_uid)
task_list_sharee(task_list_uid)