是否存在与SQL表达式NOT IN
相当的关系代数?
例如,如果我有关系:
A1 | A2
----------
x | y
a | b
y | x
我想删除A1在A2中的关系中的所有元组。在SQL中我可能会查询:
SELECT
*
FROM
R
WHERE
R.A1 NOT IN
(
SELECT
A2
FROM
R
)
/
真正令我感到困惑的是如何在关系代数选择运算符中进行子查询,这可能吗?:
σ这里的一些子查询 R
答案 0 :(得分:6)
在关系代数中,您可以使用carthesian产品执行此操作。类似的东西:
R - ρ a1,a2 (π a11,a21 (σ A11 = A22 (ρ a11,a21 (R)xρ a12,a22 (R))))
它为您提供匹配的行。从R中减去它以找到不匹配的行。
答案 1 :(得分:2)
开场问题让我们误入歧途。它应该是:
是否存在与SQL表达式R WHERE ... [NOT] IN S
相当的关系代数?
(也就是说,答案是两个关系之间的某些操作,不某种过滤器。)
答案是肯定的,它是(自然的)JOIN
又名领结算子⋈
。
要了解原因,让我们首先整理给出的SQL解决方案。如图所示,它正在寻找属性A1 NOT IN
与单个属性A2
的关系。这真的是属性名称的不匹配。 SQL还允许在where条件中使用NOT
。这个SQL使逻辑结构更清晰:
SELECT * FROM R
WHERE NOT (A1 IN (SELECT A2 AS A1 FROM R) )
现在我们可以看到投影和重命名。 (根据第一个答案,我们可以按照设置MINUS实现周围的NOT
。)所以等效的RA是:
R - (R ⋈ ρ
<子> A1/A2 子> (π
<子> A2 子> (R)))
有兴趣的话,教程D是:
R MINUS (R JOIN (R {A2} RENAME A2 AS A1))
在提出这个问题的方式中,SQL思维会有一些遗留问题。 SQL的WHERE
强制您进入行级“模式”。这与Codd的规则7相反,后者需要一次性设定运营商。
一般情况下,SQL的WHERE
和RA的σ
及其行级过滤器可以更简洁地实现为(自然)JOIN
,具有一次性设置逻辑。 (例如,这就是Date&amp; Darwen在 A 代数中所做的事情。)
答案 2 :(得分:0)
直接回答一个更普遍的问题:
SELECT
*
FROM
R
WHERE
R.A1 NOT IN
(
SELECT
A2
FROM
S
);
答案是:
R-R "bowtie" [R.A1=S.A2] ("pi" [A2] S )