基于 onedaywhen 的回答:
是的,缺少集合差异运算符确实会受到伤害。应该完全允许。但是,我们可以用集合补集和交集来表示集合差:
B - A = B ∩ A'
即B和A的不同实际上是B与A的补码的交集。我们将交集作为允许的运算符,虽然关系的适当补码是一件丑陋的事情,但 R1 ⊆ R 相对于 R 的补码(即 R 中不存在于 R1 中的内容)可以通过连接轻松找到:
SELECT DISTINCT R0.x
FROM R as R1
JOIN R as R0 ON R1.x<>R0.x
WHERE R1.x=val
是相对于 R 的补码
SELECT DISTINCT R.x FROM R WHERE R.x=val
所以,这里有一个谜题的解决方案,我认为:很容易得到两个或更多人保留的所有船:选择保留表中的所有船,将结果与它本身相乘,然后选择每一行都有不同的水手 1 和水手 2。在笨拙的关系代数符号中,他们教给我:
π( R.bid ) (
σ( R.bid=R2.bid and R.sid<R2.sid )( R x ρ(R, R2) )
)
(其中 π 是投影算子,σ 是选择算子,ρ 是重命名算子)
这可以获取两个或更多人预订的所有船只的 ID。现在我要去取所有由两个或更少的人预订的船。为此,我将选择三个或更多人保留的所有船,并通过从原始表中选择该集合中不存在的所有行来获取集合的补充。它不会很漂亮,但它是这样的:
π(R.bid)(σ(R.bid<>R1.bid)(
π(R.bid)(R)
x
π(R1.bid) (
σ( R1.bid=R2.bid and R2.bid=R3.bid and R1.sid<R2.sid and R2.sid<R3.sid )( ρ(R, R1) x ρ(R, R2) x ρ(R, R3) )
)
))
你看,我选择了所有具有属性的行,然后从原始表中选择了所有不属于这些的行,将所有没有属性的行都排除在外,这意味着所有没有被三个人保留的船或更多人,由两个或更少人预订的船。
要获得恰好有两个人预订的船,只需将其与不止一个人预订的船相交即可。
π( R.bid ) (
σ( R.bid=R2.bid and R.sid<R2.sid )( R x ρ(R, R2) )
) ∩ π( R.bid ) (
σ(R.bid<>R1.bid)(
π(R.bid)(R)
x
π(R1.bid) (
σ( R1.bid=R2.bid and R2.bid=R3.bid and R1.sid<R2.sid and R2.sid<R3.sid )( ρ(R, R1) x ρ(R, R2) x ρ(R, R3) )
)
)
)
啊。太丑了,让人心疼。我希望我知道一个更好的符号。
SQLishly,它可能看起来像这样,我认为:
(SELECT DISTINCT R1.bid
FROM Reserves AS R1
JOIN Reserves AS R2 ON R1.bid = R2.bid AND R1.sid < R2.sid
) INTERSECT (
SELECT DISTINCT R.bid
FROM Reserves AS R1
JOIN Reserves AS R2 ON R1.bid = R2.bid AND R1.sid < R2.sid
JOIN Reserves AS R3 ON R1.bid = R3.bid AND R2.sid < R3.sid
JOIN Reserves AS R ON R.bid<>R1.bid
)
请注意,这正是 onedaywhen 的解决方案,除了我将集差表示为取与补码的交集。