如何在关系代数中编写具有属性的select属性?

时间:2012-04-27 06:49:14

标签: sql database relational-algebra

我有一个关系,例如R(Owner,Car)。如何归还在关系代数中拥有三辆汽车的车主? (并且不使用聚合函数)

e.g。类似σ(COUNT(Car)=3)(R)但不使用聚合函数的东西?

e.g.
given            return
+-+----+         +-+----+
|a|attX|         |a|attX|
+-+----+         +-+----+
|a|attY|   ==>   |a|attY|
+-+----+         +-+----+
|a|attZ|         |a|attZ|
+-+----+         +-+----+
|b|attX|
+-+----+
|c|attW|
+-+----+
|c|attX|
+-+----+
|c|attY|
+-+----+
|c|attZ|
+-+----+

编辑:感谢您的回答,但我正在寻找如何在关系代数中编写这个。这意味着在表单中使用σπX等运算符。

3 个答案:

答案 0 :(得分:0)

你说σ(COUNT(Car)= 3)(R),但COUNT是一个聚合函数。

没有聚合,我看到的唯一方法是通过行计数所有者遍历R表行。类似的东西:

for each row
    If owner=previous_owner then n_cars++ 
    else (if n_cars>=3 then return owner
end

答案 1 :(得分:0)

\pi_{Car.owner}(\sigma_{Car.owner = C1.owner\wedge 
                        C1.owner = C2.owner\wedge 
                        Car.vin != C1.vin\wedge 
                        C1.vin != C2.vin\wedge 
                        Car.vin != C2.vin}(Car x 
                                           \rho_{C1}(Car) x 
                                           \rho_{C2}(Car)))
 -
 \pi_{Car.owner}(\sigma_{Car.owner = C1.owner\wedge 
                        C1.owner = C2.owner\wedge 
                        C2.owner = C3.owner \wedge
                        Car.vin != C1.vin\wedge 
                        C1.vin != C2.vin\wedge 
                        Car.vin != C2.vin \wedge
                        Car.vin != C3.vin\wedge 
                        C1.vin != C3.vin\wedge 
                        C2.vin != C3.vin}(Car x 
                                           \rho_{C1}(Car) x 
                                           \rho_{C2}(Car) x
                                           \rho_{C3}(Car)))

其中\pi为投影,\sigma为选择,x为笛卡尔积,\rho为重命名,\wedge代表连词,我假设属性为关系汽车被称为ownervin

答案 2 :(得分:-1)

这是一种方法,在SQL中使用易于转换为关系代数的运算符,并使用稍微不同的测试数据(不同类型,相同名称):

WITH R 
     AS
     (
      SELECT * 
        FROM (
              VALUES (1, 1), 
                     (2, 2), (2, 3),
                     (3, 1), (3, 2), (3, 3),
                     (4, 1), (4, 2), (4, 3), (4, 4)
             ) AS T (Owner, Car)
     ),
     OwnersWithAtLeastThreeCars
     AS
     (
      SELECT DISTINCT R1.Owner
        FROM R AS R1, R AS R2, R AS R3
       WHERE R1.Owner = R2.Owner
             AND R2.Owner = R3.Owner
             AND R1.Car <> R2.Car
             AND R1.Car <> R3.Car
             AND R2.Car <> R3.Car
     ),
     OwnersWithAtLeastFourCars
     AS
     (
      SELECT DISTINCT R1.Owner
        FROM R AS R1, R AS R2, R AS R3, R AS R4
       WHERE R1.Owner = R2.Owner
             AND R2.Owner = R3.Owner
             AND R3.Owner = R4.Owner
             AND R1.Car <> R2.Car
             AND R1.Car <> R3.Car
             AND R1.Car <> R4.Car
             AND R2.Car <> R3.Car
             AND R2.Car <> R4.Car
             AND R3.Car <> R4.Car
     )
SELECT * FROM OwnersWithAtLeastThreeCars
EXCEPT       
SELECT * FROM OwnersWithAtLeastFourCars;

P.S。我正在使用'旧式'(即1992年之前)的标准SQL连接,这些连接在Stackoverflow上受到广泛的谴责。我使用它们不仅因为它符合OP的可用运算符列表,而且坦率地说,在这些情况下,我发现它们比使用中缀INNER JOIN符号更容易编写。