2014-10-09 32 views
1

我试图更好地理解关系代数,并且在解决以下类型的问题时遇到了问题:如何查找所有A的子类别B都与同一列C相关的列?

假设有一列A(Department),一列B(Employees)和一列C(经理)。我怎样才能找到所有员工都只有一名经理的部门?提供一个例子如下:

Department | Employees | Managers 
-------------+-------------+---------- 
    A   | John  | Bob 
    A   | Sue  | Sam 
    B   | Jim  | Don 
    B   | Alex  | Don 
    C   | Jason  | Xie 
    C   | Greg  | Xie 

在该表中,因此我应该得到的是含有部门B和C的所有元组,因为他们所有的员工都是由同一人(唐和谢分别)管理。然而,A部门不会因为员工有多个经理而被退回。

任何帮助或指针,将不胜感激。

回答

0

这类问题通常要求进行自连接。

将Department上的关系加入到自身上,然后过滤掉Managers相等的元组会产生所有不需要的元组,这些元组我们可以从原始关系中减去。

以下是我会做:

T - \pi_{T.Department, T.Employee, T.Manager} \left(\sigma_{T.Manager \neq T2.Manager \land T.Department = T2.Department}\left(\rho(T, T_2) \times T\right) \right)

首先我们做表T的副本,并将其命名为T2,然后采取T和T2的积。从结果我们选择所有的行,其中T1.Manager/= T2.Manager但T1.Department = T2.Department,产生我们这些元组:

T1.Department | T1.Employees| T1.Managers | T2.Managers | T2.Employees | T2.Department 
--------------+-------------+-------------+-------------+--------------+-------------- 
    A   | John  | Bob  | Sam   | Sue   | A 
    A   | Sue  | Sam  | Bob   | John   | A 

部门A和B是不存在的,因为他们的T1。管理器始终等于T2.Manager。

然后我们只是减去这个结果的原始设置得到答案。

0

如果您的RDBMS支持公共表表达式:

with C as (
    select department, manager, count(*) as cnt 
    from A 
    group by department, manager 
), 
B as (
    select department, count(*) as cnt 
    from A group by department 
) 
select A.* 
from A 
join C on A.department = C.department 
join B on A.department = B.department 
where B.cnt = C.cnt; 
+1

谢谢,但我不能使用聚合函数,如计数(因此不能组)。我试图用关系代数来解决这个问题。 – n0shadow 2014-10-09 14:21:46

相关问题