简体   繁体   English

编写此SQL查询的更好方法是什么?

[英]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 在那种情况下,只有一行为极致而没有其他人

Sql Fiddle Demo 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

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. 不存在是非常有效的,因为它在找到第一次出现时停止搜索。

SQL Fiddle SQL小提琴

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM