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

whitzsjs  于 2023-01-16  发布在  Mysql
关注(0)|答案(1)|浏览(114)

这更多的是出于好奇/科学兴趣,而不是基于一真实的问题。
编程语言应该是一种工具,而工具是为了使工作更容易而制造的。那么,为什么你可以通过简单地执行SELECT * FROM foo WHERE bar=42;来找到一个表中的所有条目,但一旦涉及到多个表,就没有简单/直观的方法来说“找到满足此条件的所有元组”呢?
这个例子是关于被运送到不同城市的不同项目的组件。主键用粗体表示。

component(**CNR**,Cname,Color,Weight,City)
project(**PNR**,Pname,City)
scp(**SNR**,**CNR**,**PNR**,Quantity)

任务是编写一个查询,以查找已发运到某个特定城市的所有项目的所有组件。
给定溶液:

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 ));

它是正确的,有道理的,甚至有效。但它不是直观的--一个直截了当的“给我拿这个”的声明。为什么?
我们课程中的示例和所有材料都基于SQL 92。

s4n0splo

s4n0splo1#

你的问题是:“查找已发运到某个特定城市的所有项目的所有组件。”您将其改写为“查找在给定城市中没有项目的所有组件。”
我更倾向于直接回答:

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可能会对性能不利;然而,我确实认为这更容易理解。

相关问题