2015-10-21 30 views
1

我有三個表的方案具有以下結構SQL查詢來獲得每一個可能的環節

donuts (name: string, price: integer) 
grocery (no: string, gname: string, credit: integer) 
distributor (dname: string, gno: string, deliverydate: date) 

distributor.dname和distributor.gno是引用甜甜圈和雜貨店外鍵,其鍵名,沒有respectivey 我有2個查詢我想寫麻煩:

  1. 我想查詢誰是在每一個「馮氏公司」或「史密斯」雜貨店所有甜甜圈的名稱。 (在的gname指定)

我試圖

SELECT d.name 
FROM donuts d, grocery g, distributor dd 
WHERE d.name = dd.cname 
     AND dd.gno = g.no 
     AND g.gname = 'Vons' OR g.gname = 'Smiths' 
  • 我想查詢雜貨數(在雜貨店無)由ATLEAST兩個不同的甜甜圈共享。
  • 我試圖

    SELECT g.no 
    FROM donuts d, grocery g, distributor dd 
    WHERE g.no = dd.gno 
    

    這似乎並沒有返回或每一次出現或帳戶。我怎樣才能解決我的疑問?我對SQL有點新,請原諒我缺乏知識。

    +0

    你應該真的使用Id值作爲你的外鍵引用而不是字符串值。 – Siyual

    +0

    你用什麼服務器'mysql'或'sql'? – Alex

    +1

    sql是一種語言,而不是服務器。 – Nathan

    回答

    1

    1)您使用的組合和和OR查詢,你需要使用括號來指定order of operations,否則OR條款不會按照您的意圖進行解釋。例如,使用括號:

    SELECT d.name 
    FROM donuts d, grocery g, distributor dd 
    WHERE d.name = dd.cname 
         AND dd.gno = g.no 
         AND (g.gname = 'Vons' OR g.gname = 'Smiths') 
    

    在上面的例子中,括號確保OR操作是僅在兩個的gname值之間,而不是的gname之間=「史密斯」和where子句的其餘部分。 2)假設數據只有每個雜貨店 - 分銷商 - 甜甜圈關係的一個實例,並且每個雜貨店只從一個分銷商處獲得每個甜甜圈類型,則應該能夠對行進行計數並應用HAVING子句來查找哪裏有兩個或兩個以上的關係:

    SELECT g.no, COUNT(*) as Quantity 
    FROM distributor dd, grocery g, donuts d 
    WHERE dd.dname = d.name 
    AND dd.gno = g.no 
    GROUP BY g.no 
    HAVING COUNT(*) >= 2 
    
    +0

    如果我想要在每家商店檢查甜甜圈的名稱,我會忽略最後的AND語句?只是想明白。它會讓每個結果都正確嗎? –

    +0

    是的,沒錯。您的WHERE子句包含表格之間的鏈接(「連接」)和過濾條件(對於gname)。這實際上是一種較舊的SQL編寫風格,現在更受歡迎的方式是將表之間的鏈接編寫爲FROM子句中的JOIN條件,並讓WHERE子句僅包含篩選條件 - 您的問題的其他答案之一有這種查詢風格的例子。 – Nathan

    1

    嘗試使用最後一個或括號括起來,它可能只是試圖尋找與vons相連的密鑰,然後是沒有密鑰連接的smiths。

    SELECT d.name 
    FROM donuts d, grocery g, distributor dd 
    WHERE d.name = dd.cname 
         AND dd.gno = g.no 
         AND (g.gname = 'Vons' OR g.gname = 'Smiths') 
    
    +0

    這是否會返回每個甜甜圈的名稱? –

    +0

    我相信是的,是的 –

    0

    我猜你只需要JOIN表正確:

    SELECT DISTINCT d.name 
    FROM grocery g 
    LEFT JOIN distributor dd 
    ON dd.gno = g.no 
    LEFT JOIN donuts d 
    ON d.name = dd.cname 
    WHERE g.gname = 'Vons' OR g.gname = 'Smiths' 
    
    0

    甜甜圈兩個馮氏公司和史密斯

    沒有必要從表中選擇賣出,因爲我們需要從它donauts的名字,這是我們也可在distributor中找到。

    因此,我們從grocery中選擇以獲取店鋪號碼並使用它們來查找distributor中的dname。我們按甜甜圈名稱分組,並簡單地計數他們的商店。

    select dname 
    from distributor 
    where gno in (select no from grocery where gname in ('Vons', 'Smiths')) 
    group by dname 
    having count(distinct gno) = 2; 
    

    如果dname + gnodistributor唯一可以用count(*)取代count(distinct gno)

    商店銷售至少兩個不同的甜甜圈

    你的第二個查詢轉換爲

    select g.no 
    from donuts d 
    cross join grocery g 
    inner join distributor dd on dd.gno = g.no 
    

    適當加入。所以你先把所有的甜甜圈和所有的雜貨結合起來。然後,你們將這些與商店中分發的所有甜甜圈相乘。

    你真正想要的是

    select gno 
    from distributor 
    group by gno 
    having count(distinct dname) > 1; 
    

    同樣無需查詢任何其他表;所有需要的信息在distributor