为啥 SQL 中无法避免双重嵌套的 NOT EXISTS 语句
Posted
技术标签:
【中文标题】为啥 SQL 中无法避免双重嵌套的 NOT EXISTS 语句【英文标题】:Why are double nested NOT EXISTS statements unavoidable in SQL为什么 SQL 中无法避免双重嵌套的 NOT EXISTS 语句 【发布时间】:2014-12-31 14:23:53 【问题描述】:这更多是出于好奇/科学兴趣,而不是基于实际问题,我曾经向我的数据库讲师询问过这个问题,但他无法回答/理解我的问题。所以我决定来这里。
编程语言应该是一种工具,而工具是为了让工作更轻松,对吧?那么为什么您可以通过简单地执行SELECT * FROM foo WHERE bar=42;
在一个表中找到所有条目。但是一旦涉及到多个表,就没有简单/直观的方式来说“找到所有满足此条件的元组”?
脚本中给定的示例是这样的(这是从德语翻译过来的,所以命名可能有点混乱):
对于以下格式的表格:
组件(CNR,Cname,Color,Weight,City) 项目(PNR,Pname,City) scp(SNR,CNR,PNR,数量)粗体显示的主键。该示例是关于运送到不同城市的不同项目的组件。
任务是编写一个查询以查找所有已运送/已运送到特定城市的所有项目的组件。
给定的解决方案如下所示:
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 的。
感谢您的回答
【问题讨论】:
这是一种可能的解决方案。如果您想使用更直观的解决方案,请使用一个 - 但如果您希望我们找到一个,那么您必须定义“直观” 直观地说,我的意思是“给我这个”的直截了当的陈述,就像你只在一张桌子上操作一样。像上面的解决方案这样的陈述是相当困难的。主要是因为双重否定。无论是通过谷歌搜索还是自己尝试,我都找不到更简单的方法。所以这一定是有原因的。 在我看来原因是您的解决方案需要证明是否定的。 SQL 设置为易于获得肯定:“获取满足此条件的所有结果”。但是您需要“获取此条件没有例外的所有结果”。如果你能想出一种重新发明 SQL 的方法,让它直观地做到这两点,你可能会成为下一个亿万富翁,但我认为这不会像你想象的那么容易。 “给定的解决方案”并没有像你想象的那样做。建立一些表并进行测试。 如果我没记错的话,查询会执行所谓的关系除法,为什么从未实施过特定的关系操作对我来说是个谜;我们确实得到了联合、交叉和差异,但从来没有分裂。也许实施起来太难了。不过set1 divided by set2
会很好。
【参考方案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'
);
这会计算城市中不同项目的数量,并将它们与城市中的项目数量进行比较(distinct
id 在子查询中可能不需要。
首先,我不确定这是否更简单。其次,我是第一个承认NOT EXISTS
方法可能更有效,尽管在子查询中嵌套NOT EXISTS
可能会损害性能。不过,我确实认为这更容易理解。
【讨论】:
我喜欢你避免否定的方式,我支持你,当你在几周后回到这个问题时,它会让你更容易理解。 是的,对我来说更容易理解。所以这实际上是可能的,尽管我们被告知并非如此。只要我有时间回到那个练习,我就会测试这个。还有很多其他的事情要做。所以这可能需要几天时间。谢谢你的回答。我会将其标记为已解决以上是关于为啥 SQL 中无法避免双重嵌套的 NOT EXISTS 语句的主要内容,如果未能解决你的问题,请参考以下文章