[英]What is a better way to write this SQL query?
I have the following relations. 我有以下关系。
Suppliers( sid: integer, sname: string, address: string)
Parts(pid: integer, pname: string, color: string)
Catalog( sid: integer, pid: integer, cost: real)
The problem asks me to find the pnames of parts supplied by Acme Widget Suppliers and no one else. 这个问题要求我找到Acme Widget Suppliers提供的零件的pnames,而不是其他人。 I wrote the following SQL statement; 我写了以下SQL语句; however I feel like this query is inefficient because of the repetition. 但是我觉得这个查询由于重复而效率低下。 I would like to know if there is a better way to write this query without repeating the selecting catalog part. 我想知道是否有更好的方法来编写此查询而不重复选择目录部分。
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"
)
);
I use left join
on the second part because I expect get nulls
. 我在第二部分使用left join
,因为我希望得到nulls
。 In that case only one row for acme and no one else 在那种情况下,只有一行为极致而没有其他人
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
The correct query would be: 正确的查询将是:
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)
The not exist is very efficient as it stops to search when it finds the first occurence. 不存在是非常有效的,因为它在找到第一次出现时停止搜索。
I would just try joining together the three tables, then restricting with the WHERE
clause you already were using. 我只是尝试将三个表连接在一起,然后使用您已经使用的WHERE
子句进行限制。 I used DISTINCT
in the SELECT
statement to ensure that duplicates get taken out, should they occur. 我在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"
This can work: 这可以工作:
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)
The inner select
is meant to find exclusive parts from any supplier. 内部select
旨在寻找任何供应商的独家零件。 If a part is sold by multiple providers, it will not be included. 如果某个零件由多个供应商销售,则不会包含该零件。
Working example: http://sqlfiddle.com/#!6/1ccde/10 工作示例: http : //sqlfiddle.com/#!6/1ccde/10
To provide another way to tackle this one here a variant using grouping of data. 为了提供另一种解决这个问题的方法,这里有一个使用数据分组的变体。 It is a solution to select all pnames that were provided by and only by 'Acme Widget Suppliers' 这是一个选择由'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'
The select groups by pname and calculates the min and max of suppliers name. 按pname选择组并计算供应商名称的最小值和最大值 。 If there are different suppliers of one part min and max are not equal. 如果有一个零件的不同供应商最小和最大不相等。
As I understand the nuance within the question (Part provided by 'Acme' or Part provided by 'Acme' and no one else) is still not clear, I will stick to the later and more difficult selection ;). 据我所知,问题中的细微差别(部分由'Acme'提供或部分由'Acme'提供而且没有其他人)仍然不清楚,我会坚持后来更难选择;)。
You are correct. 你是对的。 The query you want to make can be greatly simplified. 您想要进行的查询可以大大简化。 Try the following. 请尝试以下方法。
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"
As per your query, seems to be not in not required also exists
statement is much better than in
and join. 根据你的查询,似乎不是不需要也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.