簡體   English   中英

編寫此SQL查詢的更好方法是什么?

[英]What is a better way to write this SQL query?

我有以下關系。

Suppliers( sid: integer, sname: string, address: string)
Parts(pid: integer, pname: string, color: string)
Catalog( sid: integer, pid: integer, cost: real)

這個問題要求我找到Acme Widget Suppliers提供的零件的pnames,而不是其他人。 我寫了以下SQL語句; 但是我覺得這個查詢由於重復而效率低下。 我想知道是否有更好的方法來編寫此查詢而不重復選擇目錄部分。

Select P.pname 
FROM Parts P 
WHERE P.pid IN (
    Select C.pid 
    FROM Catalog C 
    INNER JOIN Supplier S
    ON S.sid = C.sid 
    WHERE S.sname = "Acme Widget Suppliers" 
    AND C.pid NOT IN (
            SELECT C2.pid 
            FROM Catalog C2
            INNER JOIN Supplier S
            ON S.sid = C2.sid 
            WHERE S.sname <> "Acme Widget Suppliers"
        )
);

我在第二部分使用left join ,因為我希望得到nulls 在那種情況下,只有一行為極致而沒有其他人

Sql小提琴演示

Select *
FROM Parts P 
INNER JOIN Catalog C1
   ON P.pid = C1.pid
INNER JOIN Suppliers S1
   ON C1.sid = S1.sid
LEFT JOIN Catalog C2
   ON P.pid = C2.pid
  AND C1.sid <> C2.sid
WHERE 
   S1.sname = 'Acme' 
AND C2.sid IS NULL

正確的查詢將是:

Select P.PName from Suppliers S1 
 join Catalog C1
  on S1.sid = C1.sid
  join parts P
   on P.pid = C1.pid
where  S1.sname = 'Acme Widget Suppliers'
 and not exists 
 ( select  1 from catalog C2 where C2.sid != C1.sid 
   and C2.pid = C1.pid)

不存在是非常有效的,因為它在找到第一次出現時停止搜索。

SQL小提琴

我只是嘗試將三個表連接在一起,然后使用您已經使用的WHERE子句進行限制。 我在SELECT語句中使用了DISTINCT來確保重復項被刪除,如果它們發生的話。

SELECT DISTINCT p.pname
FROM  Parts p INNER JOIN Catalog c
ON p.pid = c.pid
INNER JOIN Suppliers s
ON c.sid = s.sid
WHERE s.sname = "Acme Widget Suppliers"

這可以工作:

select p.pname from Catalog c
join Parts p on p.pid = c.pid
join Suppliers s on s.sid = c.sid
where s.sname = 'Acme Widget Suppliers'
and p.pid in (select pid as SupplierCount from Catalog c
              group by pid having count(*) = 1)

內部select旨在尋找任何供應商的獨家零件。 如果某個零件由多個供應商銷售,則不會包含該零件。

工作示例: http//sqlfiddle.com/#!6/1ccde/10

為了提供另一種解決這個問題的方法,這里有一個使用數據分組的變體。 這是一個選擇由'Acme Widget Suppliers'提供的所有pnames的解決方案

Select P.pname 
FROM Parts P 
INNER JOIN Catalog C on c.pid=p.pid
INNER JOIN Supplier S  ON S.sid = C.sid 
GROUP BY p.pname 
HAVING min(s.sname)=max(s.sname) 
   and max(s.name)='Acme Widget Suppliers'

按pname選擇組並計算供應商名稱的最小值最大值 如果有一個零件的不同供應商最小最大不相等。

據我所知,問題中的細微差別(部分由'Acme'提供或部分由'Acme'提供而且沒有其他人)仍然不清楚,我會堅持后來更難選擇;)。

你是對的。 您想要進行的查詢可以大大簡化。 請嘗試以下方法。

SELECT P.pname FROM Parts P, Suppliers S, Catalog C
WHERE C.pid = P.pid
AND C.sid = S.sid
AND S.sname == "Acme Widget Suppliers"

根據你的查詢,似乎不是不需要也exists語句比in和連接好得多。

Select P.pname 
FROM Parts P 
WHERE EXISTS (
    Select C.pid 
    FROM Catalog C 
    INNER JOIN Supplier S
    ON S.sid = C.sid 
    WHERE P.pid = C.pid  AND  S.sname = "Acme Widget Suppliers" 
);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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