簡體   English   中英

使用 group by 和 have 子句

[英]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. 獲取供應給至少兩個不同項目的零件的供應商編號和名稱。

  2. 獲取至少兩個不同項目的同一部件的供應商的供應商編號和名稱。

這些是我的回答:

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;

這個查詢的評估可以看作是以下步驟:

  1. 執行 WHERE,消除不滿足它的行。
  2. 根據 a 和 b 的值將表分組為子集(每個子集中的每個元組具有相同的 a 和 b 值)。
  3. 消除不滿足 HAVING 條件的子集
  4. 處理每個子集,輸出在查詢的 SELECT 部分中指示的值。 這將在步驟 3 之后為每個子集創建一個輸出元組。

您可以將其擴展到任何復雜的查詢,表可以是任何返回表的復雜查詢(叉積、聯接、聯合等)。

事實上,擁有只是語法糖,並沒有擴展 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 ,這是您最初想要的。

您的問題的最佳解決方案

我個人更喜歡更簡單的清潔解決方案:

  1. 您只需按 Supplies (sid、pid、jid**、quantity) 分組即可找到至少供應兩個項目的那些的 sid。
  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 中出現了子句來解決這個問題。 請參閱讓子句通過此鏈接的示例

http://www.sqlfundamental.com/have-clause.php

首先,您應該使用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. 獲取至少提供給兩個不同項目的零件供應商的供應商編號和名稱。

  2. 獲取至少兩個不同項目中相同零件的供應商的供應商編號和名稱。

這些是我的答案:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM