将嵌套的(两个)NOT IN转换为嵌套的(两个)NOT不存在

毫米

试图NOT EXISTS更好地理解即使有嵌套的情况,NOT EXISTS我们是否NOT IN可以总是替换

我发现了这个类似的问题NOT IN在尝试处理嵌套案例时只有一个问题我们有两个表,registered和preActivity。

已注册的具有mId(字符串),aId(字符串),季度(字符串),年份(整数),并且preActivity具有aId(字符串),preAId(字符串),其中

> mId is member id, 
> aId is the activity Id, 
> preAId is the prerequisite activity Id.

如果我们使用嵌套NOT NOT嵌套的查询来查找所有成员,那么在YMCA游泳活动(课程)之前,所有成员已经注册了所有必需的活动(前提)课程。我们可以将其转换为两个嵌套的NOT EXIST吗?

SELECT DISTINCT r.mid
FROM registered r
WHERE r.mid NOT IN (SELECT r.mid
                    FROM preActivity p
                    WHERE p.aid = "swimming" AND 
                    p.preAId NOT IN (SELECT r2.mid
                                     FROM registered r2
                                     WHERE r2.mid = r.mid));

使用这篇文章的提示,我们可以转换一个NOT IN,但是第二个转换要花我几个小时。有人可以帮忙做些解释吗?

这是我到目前为止的内容:

SELECT DISTINCT r.mid
FROM registered r
WHERE NOT EXISTS (SELECT r.mid
                  FROM preActivity p
                  WHERE p.aid = "swimming" AND 
                  p.preAId NOT IN (SELECT r2.mid  # how can we compare p.preAId with some rows selected from r2 Notice we don't have preAid field from resistered table (following the idea from the post? 
                                   FROM registered r2
                                   WHERE r2.mid = r.mid));

还是因为这是两个嵌套的案例,所以我们不能在这里应用相同的想法?

查理菲斯

首先要记住:查询中SELECTin[NOT] EXISTS无关紧要,因为我们只是在寻找行的存在。您甚至可以编写但SELECT 1/0不会出现错误。所以大多数人写[NOT] EXISTS (SELECT 1(我喜欢将所有内容放在一行上,并将其余子查询放在新行上)

其次,NOT IN查询可能在null列周围存在问题,因此最好始终编写一个NOT EXISTS


现在,如果您分析[NOT] IN查询,您将看到准联接位于列之前,而该列位于中SELECT因此查询:

X.colA [NOT] IN
    (SELECT Y.colA FROM Y)

始终可以转换为

[NOT] EXISTS (SELECT 1
    FROM Y
    WHERE Y.colA = X.colA)

另一个有趣的语法(对于多列连接或可为空的列最有用)是:

[NOT] EXISTS (
    SELECT X.colA
    INTERSECT
    SELECT Y.colA
    FROM Y)

不要忘记在子查询列上始终使用正确的表别名,如果您弄错了,那么查询可能会返回不正确的结果而不会引起您的注意。

例如,这里发生了什么?

[NOT] EXISTS (SELECT 1
    FROM Y
    WHERE X.colA = colA)

就您而言,您的第一个NOT IN查询有点奇怪。

您将r.mid加入连接的两面,因此EXISTS无论如何有效地变成了连接。

因此,您的查询可以这样重写:

select distinct r.mid
    from registered r
    where not exists (select 1
        From preActivity p
        where p.aid = "swimming" and 
        not exists (select 1
            From registered r2
            where r2.mid = r.mid and r2.mid = p.preAId
        )
    );

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章