如何在SQL Server中实现DIVIDE操作的关系等价物

时间:2015-01-11 06:21:04

标签: sql sql-server relational-algebra divide

我正在阅读其中一本教科书中的关系代数。 我遇到了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                        

2 个答案:

答案 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

SQLFiddle

答案 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       --  --
    )-------------------------------------------  --
)-------------

top plan with EXCEPT, bottom without EXCEPT