2

我正在做一个测试考试,我已经停留在一个特定的查询中,在它的SQL代码,关系代数和元组关系演算中。SQL查询(在SQL中,关系代数和元组关系演算)

查询状态: 查找包含Branch 关系中列出的每种类型分支的(城市,州)对。

其中Branch是:

Branch_ID (Primary key) 
Branch_City 
Branch_State 
Branch_Type 

和城市是:

City_Name (Primary key) 
State_Name (Primary key) 
Population 

而且Branch_CityBranch_State是一个外键分别City_NameState_Name

“规则”是指聚合的功能,如COUNTMAX等可以不使用

查询必须由MySQL和PostgreSQL“理解”,但是可以使用PostgreSQL中可用但不在MySQL中的函数,如EXCEPT,INTERSECT

FROM条款

由于无子查询的说,它会如果有可能为SQL,关系代数和元组关系演算提供的答案是极大的赞赏。这些问题阻碍了我。

在此先感谢!

回答

2
-- The query states: Find the (city,state) pairs which house a branch of every type which is listed in the Branch relation. 
--            ((((     ^^^^^ ^^^^ )) 
-- This is equivalent to: Find cities for which "There does NOT EXIST a branchType that is NOT PRESENT in this City" 
-- This leads to the double "NOT EXISTS (NOT EXISTS())" solution to relational devision.:: 
SELECT * -- city,state 
FROM city c 
WHERE NOT EXISTS (
     -- find a branchtype that is not present in our city 
     SELECT * FROM Branch b 
     WHERE NOT EXISTS (
       -- same city for this branchtype 
       SELECT * FROM Branch nx 
       WHERE nx.Branch_City = c.City_Name AND nx.Branch_State = c.State_Name 
       AND nx.Branch_Type = b.Branch_Type 
       ) 
     ) 
     ; 

Relational division是这类操作的术语。

顺便说一句:city表的复合(城市,州)主键只是在那里混淆你。通常,您可以使用数字(代理)city_id作为城市表的主键,并将其用作branches表中的外键。

+0

非常感谢!这非常有帮助!最后我明白了如何在“纯”SQL编程中实现分割! – Cenderze

3

这是SQL Server语法,因为我没有MySQL或PostgreSQL的,但应该给你的想法:

with branches as (
    select * from (values 
    ('Perth',1), 
    ('Toronto',1), ('Toronto',2), ('Toronto',3), 
    ('Hamilton',2), ('Hamilton',3) 
) branches(City, Branch_Type) 
) 

    select distinct 
    City 
    from branches 
except 
    select distinct 
    b.City 
    from branches t 
    cross join branches b 
    left join branches b2 on b2.Branch_Type = t.Branch_Type and b2.City = b.City 
    where b2.Branch_Type is null 

我已经削减下来到最低限度,表现出必要的设置操作。

查询的上半部分返回所有三个城市;下半场只返回汉密尔顿和珀斯;以便整个查询只返回多伦多。

30年来我没有使用关系代数或关系演算,但在这些方言中表达上述查询只是一种翻译练习。

更新 - 为MySQL:

with branches as (
    select * from (values 
    ('Perth',1), 
    ('Toronto',1), ('Toronto',2), ('Toronto',3), 
    ('Hamilton',2), ('Hamilton',3) 
) branches(City, Branch_Type) 
) 

select distinct 
    City 
from branches 
where City not in (
    select distinct 
    b.City 
    from branches t 
    cross join branches b 
    left join branches b2 on b2.Branch_Type = t.Branch_Type and b2.City = b.City 
    where b2.Branch_Type is null 
) 

由于子查询的WHERE子句,而不是FROM子句这应和合法英寸它可以表示为左连接,但我认为这会将子查询移入FROM子句。

+0

我已经开始SQL小提琴的问题,并确认您的答案适用于SQL Server http://sqlfiddle.com/#!3/48e48和PostgreSQL但不适用于MySql。 – grahamj42

+0

@ grahamj42:什么是MySql的WITH构造的等价物?是否有必要明确创建测试工作表? MySQL是否支持设置操作(即EXCEPT操作符)? –

+0

T认为有必要创建表格,这就是SQL小提琴在回答这样的问题时可以为您做的事情。 – grahamj42