使用以下架构:
Supplier (sid, name, status, city)
Part (pid, name, color, weight, city)
Project (jid, name, city)
Supplies (sid, pid, jid**, quantity)
Run Code Online (Sandbox Code Playgroud)
获取供应给至少两个不同项目的零件供应商的供应商编号和名称.
为至少两个不同的项目获取同一部件供应商的供应商编号和名称.
这些是我的答案:
1.
SELECT s.sid, s.name
FROM Supplier s, Supplies su, Project pr
WHERE s.sid = su.sid AND su.jid = pr.jid
GROUP BY s.sid, s.name
HAVING COUNT (DISTINCT pr.jid) >= 2
Run Code Online (Sandbox Code Playgroud)
2.
SELECT s.sid, s.name
FROM Suppliers s, Supplies su, Project pr, Part p
WHERE s.sid = su.sid AND su.pid = p.pid AND su.jid = pr.jid
GROUP BY s.sid, s.name
HAVING COUNT (DISTINCT pr.jid)>=2
Run Code Online (Sandbox Code Playgroud)
任何人都可以确认我是否写得正确吗?关于Group By和Having子句如何工作,我有点困惑
dmg*_*dmg 93
拥有的语义
为了更好地理解,你需要从理论的角度来看待它.
甲按组是一个查询,需要一个表,并将其汇总成另一个表.通过将原始表分组为子集(基于您在组中指定的属性)来汇总原始表.这些组中的每一组都将产生一个元组.
的有是简单地等同于WHERE子句后的组通过已执行,并且之前选择查询的一部分进行计算.
让我们说你的查询是:
select a, b, count(*)
from Table
where c > 100
group by a, b
having count(*) > 10;
Run Code Online (Sandbox Code Playgroud)
对此查询的评估可以看作以下步骤:
您可以将其扩展到任何复杂查询,Table可以是任何返回表的复杂查询(交叉产品,连接,UNION等).
事实上,有是语法糖,并且不扩展SQL的力量.任何给定的查询:
SELECT list
FROM table
GROUP BY attrList
HAVING condition;
Run Code Online (Sandbox Code Playgroud)
可以改写为:
SELECT list from (
SELECT listatt
FROM table
GROUP BY attrList) as Name
WHERE condition;
Run Code Online (Sandbox Code Playgroud)
listatt是一个列表,其中包含GROUP BY属性以及list和condition中使用的表达式.可能需要在此列表中命名一些表达式(使用AS).例如,上面的示例查询可以重写为:
select a, b, count
from (select a, b, count(*) as count
from Table
where c > 100
group by a, b) as someName
where count > 10;
Run Code Online (Sandbox Code Playgroud)
您需要的解决方案
您的解决方案似乎是正确的:
SELECT s.sid, s.name
FROM Supplier s, Supplies su, Project pr
WHERE s.sid = su.sid AND su.jid = pr.jid
GROUP BY s.sid, s.name
HAVING COUNT (DISTINCT pr.jid) >= 2
Run Code Online (Sandbox Code Playgroud)
你加入了三个表,然后使用SID为分组属性(SNAME函数依赖于它,所以它不会对组的数量产生影响,但你必须包括它,否则就不能成为选择部分的一部分该声明).然后你将删除那些不满足你条件的东西:满足pr.jid is >= 2,这是你原本想要的.
解决您问题的最佳方案
我个人更喜欢更简单的清洁解决方案:
SELECT sid, sname from
(SELECT sid from supplies
GROUP BY sid, pid
HAVING count(DISTINCT jid) >= 2
) AS T1
NATURAL JOIN
Supliers;
Run Code Online (Sandbox Code Playgroud)
它的执行速度也会更快,因为连接只在需要时完成,而不是所有时间.
--dmg
小智 5
因为我们不能使用具有聚合函数的 Where子句,如count(),min(),sum()等等.所以有了一个子句来克服sql中的这个问题.请参阅有关子句的示例通过此链接
http://www.sqlfundamental.com/having-clause.php
使用什么类型的 SQL 数据库(MSSQL、Oracle 等)?我相信你所写的是正确的。
您还可以像这样编写第一个查询:
SELECT s.sid, s.name
FROM Supplier s
WHERE (SELECT COUNT(DISTINCT pr.jid)
FROM Supplies su, Projects pr
WHERE su.sid = s.sid
AND pr.jid = su.jid) >= 2
Run Code Online (Sandbox Code Playgroud)
与尝试使用 GROUP BY 相比,它更具可读性,也更省心。但性能可能会有所不同。
| 归档时间: |
|
| 查看次数: |
104222 次 |
| 最近记录: |