考虑集合,而不是迭代器;sql语句定义所需输出集的属性(又名表/关系)
所有场地名称,以便每个乐队国家都有一个来自该国家/地区的乐队在该名称的场地中演奏
这样的结果(如果我正确理解了您的意图!)将是在该场所中至少有一个乐队演奏的一组场所。无需在bandCountry上进行迭代,因为PLAYS关系已经具有您要查找的信息,您只需消除重复项
所以在SQL中这将是:
select
distinct venueName
from PLAYS
编辑:好的,所以所需的实际设置要复杂一些。该数据库的问题是:来自所有国家的乐队在哪些场馆举办过?
因此,我们将所需集合的元素的成员资格标准定义为目标,然后向后工作以填充集合。如果场所在每个国家/地区中至少有一个乐队设有PLAYS行,则该场所是输出集的成员。我们如何获得这些信息?
一种方法是计算每个地点的不同国家/地区,并将其与所有国家/地区的数量进行比较。但是我们没有COUNTRY关系。如果我们仔细考虑一下给出的模型,就会发现所有国家/地区的集合都不是正确的标准。它是拥有至少一个频段的所有国家的集合。因此,我们不需要国家表(尽管对于归一化模型,我们应该有一个国家表),而且我们不在乎会场的国家,我们只需计算具有乐队的国家,例如(在MS-SQL中)
declare @BandCountryCount int
select
@BandCountryCount = COUNT(distinct bandCountry)
from BAND
我们可以计算每个场地的乐队国家
select
P.venueName, COUNT(distinct B.bandCountry) as VenueBandCountryCount
from PLAYS P
inner join BAND B on B.bandName = P.bandName
我们可以使用子查询将两者组合在一起
select
venueName
from (
select
P.venueName, COUNT(distinct B.bandCountry) as VenueBandCountryCount
from PLAYS P
inner join BAND B on B.bandName = P.bandName
) X
where X.VenueBandCountryCount = @BandCountryCount
现在,这不是最漂亮的查询(与临时变量和子查询相比,GROUP BY和HAVING可能被认为是更“优雅”的解决方案),但是很明显,我们追求的是那样,因此出于OP的目的,将其保留在此处。
OP的目的是学习如何将思维方式从命令式转变为声明式。为此,请查看描述的命令式解决方案正在执行的操作:
为每个场所名称遍历所有bandCountries,并为每个bandCountry获取来自其的乐队列表。如果它们都没有在场地名称中播放,请转到下一个场地名称。否则,在bandCountries迭代结束时,将会场名称添加到一组良好的会场名称中
上面的确定标准是什么?我认为是这样:
...如果其中一个[来自特定国家/地区的乐队]都不在场地名称中播放...
这是取消资格的标准。势在必行的思维过程从满满地开始,扔掉不符合标准的东西。我们正在过滤数据。
这对于简单的东西很好,但是有助于构造所需的结果集;相应的资格标准是什么,以允许人们加满水桶?
- 取消资格者:如果某个乐队国家/地区没有乐队在该场地演奏,则该场地将被取消资格
- (部分)预选赛:如果乐队国家中至少有一个乐队在某个场地演奏,那么该场地可能还可以;继续检查乐队的其他国家
- (完全)资格赛:如果每个国家/地区中至少有一个乐队在某个场地演奏,则该场地是合格的
最终的预选赛可以通过计数来简化:如果乐队的某个国家的某个地方至少有一个乐队在场地上比赛,则该乐队“满意”;场地“满意的”乐队国家的数量必须等于要获得资格的场地的乐队国家的数量。
现在我们可以通过导航来跨关系推理:
- 从VENUE关系开始[我们不需要它来回答,但这是关系导航的概念上的起点]
- 在场地名称上加入PLAYS
- 在bandName上加入BAND以获取bandCountry
- 我们不在乎乐队的名字;仅选择场地名称和乐队国家
- 我们不在乎多余的bandCountries;使用DISTRICT或GROUP BY消除重复项
- 我们只关心不同bandCountries的数量,而不关心名称
- 我们只想使用不重复bandCountries计数与bandCountries总数相同的场馆
导致返回上述解决方案(或其合理的传真)
摘要
- 集合论
- 关系导航路径
- 包容性与排他性条件(合格与不合格)