两个 SQL 表中的任何一个都有值

Either of two SQL tables have a value

我有两个 table,task_list_shareetask_list_assignee。他们都引用了 task_list table.

还有一个 task table 引用了 task_list table 因为 task 总是存在于 task_list 中.

给定一个 task,我想知道 task_list_shareetask_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)