小编典典

为什么在SQL中不可避免地要使用双重嵌套的NOT EXISTS语句

sql

这更多是出于好奇/科学兴趣,而不是基于真正的问题,我曾经问过数据库讲师这件事,但是他无法回答/理解我的问题。所以我决定过来这里。

编程语言应该是一种工具,并且可以使工作变得更容易,对吗?因此,为什么只需执行一次操作就可以在一个表中找到所有条目SELECT * FROM foo WHERE bar=42;。但是,一旦涉及到多个表,就没有简单/直观的方式说“找到满足此条件的所有元组”吗?

脚本中给定的示例是这样的(这是从德语翻译的,因此命名可能会有些混乱):

对于以下格式的表:

  • 组件( CNR ,Cname,Color,Weight,City)
  • 项目( PNR ,Pname,City)
  • scp( SNRCNRPNR ,数量)

主键以粗体显示。该示例是关于运送到不同城市的不同项目的组件的。

任务是编写一个查询,以查找/已运送到一个特定城市中所有项目的所有组件。

给定的解决方案如下所示:

SELECT CNR
FROM components
WHERE NOT EXISTS ( SELECT 1
                  FROM project
                  WHERE project.city = 'Foobar Town'
                  AND NOT EXISTS ( SELECT 1
                                 FROM scp
                                 WHERE scp.PNR = projekt.PNR
                                 AND scp.CNR = components.CNR ));

我的意思是,这是正确的,有道理,甚至可行。但这不是直观的,当然也不能使生活变得更轻松!那么我想知道这个原因在哪里呢?由于我们被告知对考试至关重要,因此我们能够编写这样的查询,因此我无法绕开它。

我还没有找到一个更简单的解决方案。既不能通过谷歌搜索,也不能自己尝试。一定有比“每个人都懒得解决这个问题”更好的理由。有任何想法吗?

该示例以及本课程中提供给学生的所有材料均基于SQL92。

谢谢您的回答


阅读 287

收藏
2021-04-28

共1个答案

小编典典

您的问题是:“查找/运送到一个特定城市中所有项目的所有组件。” 您将其改写为“查找给定城市中没有没有项目的项目的所有项目。”

我更倾向于直接回答这个问题:

select scp.component
from scp join
     projects p
     on scp.pnr = p.pnr
where p.city = 'Foobar Town'
group scp.component
having count(distinct scp.pnr) = (select count(distinct pnr)
                                  from projects
                                  where city = 'Foobar Town'
                                 );

这将计算城市中不同项目的数量,并将其与城市中项目的数量进行比较(此distinctID在子查询中可能不是必需的)。

首先,我不确定这是否更简单。其次,我是第一个承认该NOT EXISTS方法 可能 更有效的方法,尽管NOT EXISTS子查询中的嵌套可能会对性能造成不利影响。但是,我确实认为这更容易理解。

2021-04-28