这是架构:
alt text http://img30.imageshack.us/img30/3324/123vk.jpg
这是一个问题:
指出来自同一国家的至少三艘船参加的战斗。
这是我的回答:
SELECT battles.name
FROM battles,
outcomes,
ships,
classes
WHERE outcomes.ship = ships.name
GROUP BY battles.name
HAVING COUNT(classes.country) >= 3;
你能告诉我为什么这是错的,并帮我纠正它!
答案 0 :(得分:5)
此:
SELECT battles.name
FROM battles,
outcomes,
ships,
classes
WHERE outcomes.ship = ships.name
...从根本上存在缺陷,因为OUTCOMES
和SHIPS
之间只有加入条件。结果是笛卡尔积。它是有效的 ANSI-89语法,但不会返回类似于您期望的结果集。
如果你只想要战斗“名字”,请使用:
SELECT o.battle
FROM OUTCOMES o
JOIN SHIPS s ON s.name = o.ship
JOIN CLASSES c ON c.class = s.class
GROUP BY o.battle
HAVING COUNT(c.country) >= 3
如果您想要战斗表详细信息,请使用:
SELECT b.*
FROM BATTLES b
JOIN (SELECT o.battle
FROM OUTCOMES o
JOIN SHIPS s ON s.name = o.ship
JOIN CLASSES c ON c.class = s.class
GROUP BY o.battle
HAVING COUNT(c.country) >= 3) x ON x.battle = b.name
答案 1 :(得分:4)
SELECT DISTINCT BattleName
FROM (
SELECT Battles.name AS BattleName, Class.Country, COUNT(*)
FROM Battles
JOIN Outcomes ON battles.name = Outcomes.battle
JOIN Ships ON Outcomes.ship = Ships.name
JOIN Classes ON Ships.class = Class.class
GROUP BY battles.name, Classes.country
HAVING COUNT(*) >= 3;
)
原始查询中的主要缺陷是表格之间的连接没有表达,导致了普通的笛卡尔积。
另一个问题是该国家/地区未列入允许按国家计算船舶的情况。然后将此修改后的查询作为子查询,以允许仅选择一次BattleName。
注意:
- 我在SELECT列表中添加了COUNT(*)。这更多是出于安全/无知,我认为某些SQL实现需要在HAVING子句中找到的聚合值存在于SELECT列表中。 (我可能错了)
- 而不是COUNT(*)
可能需要使用说COUNT(Classes.country)或任何其他字段(如果出现此MS-Access,则可能不允许使用COUNT(*)
语法。)
答案 2 :(得分:1)
SELECT
battles.name
FROM battles,
outcomes,
ships,
classes
WHERE battles.name=outcome.battle
AND outcomes.ship = ships.name
AND ships.class=classes.class
GROUP BY battles.name
HAVING COUNT(classes.country) >= 3;
答案 3 :(得分:1)
select distinct A.battle
from
(select country, o.battle from outcomes o
left join ships s
on s.name = o.ship
left join classes c
on c.class = s.class
group by o.battle, country
having count(country) >= 3) A
答案 4 :(得分:0)
我从未使用过GROUP BY语句的HAVING子句。但是,GROUP BY应仅用于聚合目的。因此,如果您没有选择agregation函数(SUM,MAX,MIN,AVG,COUNT等),您将无法进行GROUP BY。
答案 5 :(得分:0)
你搞砸了桌子上的连接。您不能只列出表格,您必须指定它们如何连接在一起
From Battles
Inner Join Outcomes On Outcomes.Battle = Battles.name
Inner Join Ships.Name On Ship.Name = Outcomes.Ship
Inner Join Classes.Class = Ship.Class
答案 6 :(得分:0)
我看不到你的形象(由大哥过滤掉)
但是,请记住,WHERE
首先过滤整个行,GROUP BY
合并剩余的行,Having
过滤这些行。
FROM
& JOIN
确定&过滤行
WHERE
行上的更多过滤器
GROUP BY
将这些行组合成组
HAVING
过滤群组
ORDER BY
安排剩余的行/组
答案 7 :(得分:0)
scrollHeight
这将解决您的问题。