[英]Using group by and having clause
使用以下架構:
Supplier (sid, name, status, city)
Part (pid, name, color, weight, city)
Project (jid, name, city)
Supplies (sid, pid, jid**, quantity)
獲取供應給至少兩個不同項目的零件的供應商編號和名稱。
獲取至少兩個不同項目的同一部件的供應商的供應商編號和名稱。
這些是我的回答:
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
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
誰能確認我寫的是否正確? 我對 Group By 和 Have 子句的工作方式有些困惑
擁有的語義
為了更好地理解擁有,你需要從理論的角度來看待它。
group by是一個查詢,它獲取一個表並將其匯總到另一個表中。 您可以通過將原始表分組為子集來匯總原始表(基於您在分組依據中指定的屬性)。 這些組中的每一個都將產生一個元組。
在HAVING是簡單地等同於WHERE子句的組由已執行,並且查詢的選擇部分被計算之前后。
假設您的查詢是:
select a, b, count(*)
from Table
where c > 100
group by a, b
having count(*) > 10;
這個查詢的評估可以看作是以下步驟:
您可以將其擴展到任何復雜的查詢,表可以是任何返回表的復雜查詢(叉積、聯接、聯合等)。
事實上,擁有只是語法糖,並沒有擴展 SQL 的功能。 任何給定的查詢:
SELECT list
FROM table
GROUP BY attrList
HAVING condition;
可以改寫為:
SELECT list from (
SELECT listatt
FROM table
GROUP BY attrList) as Name
WHERE condition;
listatt 是一個列表,其中包括 GROUP BY 屬性以及列表和條件中使用的表達式。 可能需要在此列表中命名一些表達式(使用 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;
您需要的解決方案
您的解決方案似乎是正確的:
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
你join這三個表,然后使用sid作為分組屬性(sname在功能上依賴於它,所以它對組數沒有影響,但是你必須包含它,否則它不能成為select部分的一部分該聲明)。 然后您將刪除那些不滿足您的條件的:滿足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;
執行速度也會更快,因為連接僅在需要時完成,而不是所有時間。
--dmg
因為我們不能將 Where 子句與count()、min()、sum()等聚合函數一起使用,所以在 sql 中出現了子句來解決這個問題。 請參閱讓子句通過此鏈接的示例
首先,您應該使用JOIN
語法而不是FROM table1, table2
,並且您應該始終將分組限制為您需要的盡可能少的字段。
我還沒有測試過,你的第一個查詢對我來說似乎很好,但可以重寫為:
SELECT s.sid, s.name
FROM
Supplier s
INNER JOIN (
SELECT su.sid
FROM Supplies su
GROUP BY su.sid
HAVING COUNT(DISTINCT su.jid) > 1
) g
ON g.sid = s.sid
或簡化為:
SELECT sid, name
FROM Supplier s
WHERE (
SELECT COUNT(DISTINCT su.jid)
FROM Supplies su
WHERE su.sid = s.sid
) > 1
但是,您的第二個查詢對我來說似乎是錯誤的,因為您還應該GROUP BY pid
。
SELECT s.sid, s.name
FROM
Supplier s
INNER JOIN (
SELECT su.sid
FROM Supplies su
GROUP BY su.sid, su.pid
HAVING COUNT(DISTINCT su.jid) > 1
) g
ON g.sid = s.sid
正如您在上面的查詢中可能已經注意到的那樣,我使用了INNER JOIN
語法來執行過濾,但是它也可以寫成:
SELECT s.sid, s.name
FROM Supplier s
WHERE (
SELECT COUNT(DISTINCT su.jid)
FROM Supplies su
WHERE su.sid = s.sid
GROUP BY su.sid, su.pid
) > 1
使用什么類型的 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
與嘗試使用 GROUP BY 相比,它更具可讀性,也更容易讓人費解。 性能可能有所不同。
1.獲取供應給至少兩個不同項目的零件的供應商編號和名稱。
SELECT S.SID, S.NAME
FROM SUPPLIES SP
JOIN SUPPLIER S
ON SP.SID = S.SID
WHERE PID IN
(SELECT PID FROM SUPPPLIES GROUP BY PID, JID HAVING COUNT(*) >= 2)
我不太清楚你的第二個問題
使用以下架構:
Supplier (sid, name, status, city)
Part (pid, name, color, weight, city)
Project (jid, name, city)
Supplies (sid, pid, jid**, quantity)
獲取至少提供給兩個不同項目的零件供應商的供應商編號和名稱。
獲取至少兩個不同項目中相同零件的供應商的供應商編號和名稱。
這些是我的答案:
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
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
任何人都可以確認我是否寫得正確嗎? 我對Group By and Haveing子句的工作方式有些困惑
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.