我正在阅读其中一本教科书中的关系代数。 我遇到了DIVIDE operation。来自维基百科:
除法是一个二进制运算,写成R÷S。结果包括R中元组对R独有的属性名的限制,即在R的标题中但不在S的标题中,对于它认为它们与S中的元组的所有组合都存在于R中。
因此如果R是:
+----+----+
| A | B |
+----+----+
| a1 | b1 |
| a2 | b1 |
| a3 | b1 |
| a4 | b1 |
| a1 | b2 |
| a3 | b2 |
| a2 | b3 |
| a3 | b3 |
| a4 | b3 |
| a1 | b4 |
| a2 | b4 |
| a3 | b4 |
+----+----+
和S是:
+----+
| A |
+----+
| a1 |
| a2 |
| a3 |
+----+
然后输出应该是:
+----+
| B |
+----+
| b1 |
| b4 |
+----+
现在,本书提供了计算DIVIDE操作的关系等效步骤,如下所示。 我试图在SQL Server中完全模仿它,但是没有方向
T1 ← πBR //that is SELECT A FROM R T2 ← πB((S x T1) - R) //SxT1 can simply be done as SELECT * FROM S,T1 T ← T1 - T2
答案 0 :(得分:2)
公式中存在不准确之处。在您的特定情况下,您需要在B
上进行投影,而不是A
上的投影,否则B
属性将如何显示在结果中?
T1 ← πBR
T2 ← πB((S x T1) - R)
T ← T1 - T2
查询:
-- T ← T1 - T2 -------------------------------------
SELECT DISTINCT B FROM R -- T1 ← πBR --
WHERE B NOT IN ( --
-- T2 ← πB((S x T1) - R) ------------------- --
SELECT CR.B -- --
FROM ( -- --
-- (S x T1) -------------------- -- --
SELECT S.A, R2.B -- -- --
FROM S -- -- --
CROSS JOIN ( -- -- --
-- T1 ← πBR -- -- --
SELECT DISTINCT B FROM R -- -- --
) AS R2 -- -- --
-------------------------------- -- --
) AS CR -- --
WHERE NOT EXISTS ( -- --
SELECT * -- --
FROM R -- --
WHERE R.A = CR.A AND R.B = CR.B -- --
)------------------------------------------- --
)---------------------------------------------------
结果:
B
--
b1
b4
答案 1 :(得分:1)
关系代数公式中存在错误印记。应该πA
而不是πB
。
创建样本表:
DECLARE @R TABLE (A varchar(10), B varchar(10));
INSERT INTO @R (A, B) VALUES ('a1','b1');
INSERT INTO @R (A, B) VALUES ('a2','b1');
INSERT INTO @R (A, B) VALUES ('a3','b1');
INSERT INTO @R (A, B) VALUES ('a4','b1');
INSERT INTO @R (A, B) VALUES ('a1','b2');
INSERT INTO @R (A, B) VALUES ('a3','b2');
INSERT INTO @R (A, B) VALUES ('a2','b3');
INSERT INTO @R (A, B) VALUES ('a3','b3');
INSERT INTO @R (A, B) VALUES ('a4','b3');
INSERT INTO @R (A, B) VALUES ('a1','b4');
INSERT INTO @R (A, B) VALUES ('a2','b4');
INSERT INTO @R (A, B) VALUES ('a3','b4');
DECLARE @S TABLE (A varchar(10));
INSERT INTO @S (A) VALUES ('a1');
INSERT INTO @S (A) VALUES ('a2');
INSERT INTO @S (A) VALUES ('a3');
给定关系代数公式的字面翻译将是这样的(在SQL Server 2008中尝试过)。 x
运算符为CROSS JOIN
,-
运算符为EXCEPT
。
WITH
T1
AS
(
SELECT B
FROM @R
)
,T2
AS
(
SELECT SS.A, T1.B
FROM
@S AS SS CROSS JOIN T1
EXCEPT
SELECT RR.A, RR.B
FROM @R AS RR
)
SELECT T1.B
FROM T1
EXCEPT
SELECT T2.B
FROM T2
;
结果集:
B
b1
b4
有趣的是,使用EXCEPT
的变体和Andrey Morozov变体的执行计划几乎完全相同。我喜欢SQL Server查询优化器!顶级计划使用EXCEPT(参见上面的查询),底部计划没有EXCEPT(请参阅@Andrey Morozov的回答中的查询,我在这里为我的临时表进行了调整):
SELECT DISTINCT B FROM @R -- T1 ← πBR --
WHERE B NOT IN ( --
-- T2 ← πB((S x T1) - R) ------------------- --
SELECT CR.B -- --
FROM ( -- --
-- (S x T1) -------------------- -- --
SELECT S.A, R2.B -- -- --
FROM @S AS S -- -- --
CROSS JOIN ( -- -- --
-- T1 ← πBR -- -- --
SELECT DISTINCT B FROM @R -- -- --
) AS R2 -- -- --
-------------------------------- -- --
) AS CR -- --
WHERE NOT EXISTS ( -- --
SELECT * -- --
FROM @R AS R -- --
WHERE R.A = CR.A AND R.B = CR.B -- --
)------------------------------------------- --
)-------------