1

Schema:

Suppliers(sid: integer, sname: string, address: string)

Parts(pid: integer, pname: string, color: string)

_Catalog(sid: integer, pid: integer, cost: real)

And the question is:

Find the sids of suppliers who supply some red part or are at 221 Packer Ave.

I've tried different methods like:

Method 1:

select sid 
from   Suppliers 
where  sid = (select pid 
              from parts 
              where color= 'Red') 
or     address='221 Packer Ave';

Method 2:

select sid 
from   _Catalog 
where  (pid IN(select pid from Parts where color='Red') 
        OR 
        sid IN(select sid from Suppliers where address='221 Packer Ave'));

It shows no output in the 2nd method and returns an error in the 1st method Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression. What am i doing wrong? and Is there any other, solution to this?

NOTE: I need a nested query to solve this problem, because I've not studied joins and advance stuff yet.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Ahsan
  • 412
  • 5
  • 17

5 Answers5

1

Just figured it out :)

select sid from Suppliers where address='221 Packer Ave' or sid IN (select sid from _Catalog where pid IN(select pid from Parts where color = 'Red'));
Ahsan
  • 412
  • 5
  • 17
0

If you can manage more than a value you can use IN clause

select sid 
from   Suppliers 
where  sid IN   (select sid
              from parts  p 
              inner join _Catalog c c.pid= p.pid
              where p.color= 'Red') 
or     address='221 Packer Ave';

you could use an aggregation function eg: max

select sid 
from   Suppliers 
where  sid = (select max(sid)
              from parts  p 
              inner join _Catalog c c.pid= p.pid
              where p.color= 'Red') 
or     address='221 Packer Ave';

or you can limit the number or rows selected eg: TOP 1

ScaisEdge
  • 131,976
  • 10
  • 91
  • 107
0

It happens because:

select pid 
from parts 
where color= 'Red'

returns more than one pid, and you are using = on your where condition.

Use IN or limit the returned pid to one row.

select top (1) pid 
from parts 
where color= 'Red'
McNets
  • 10,352
  • 3
  • 32
  • 61
0

The best way to solve the problem would be a JOIN instead of derived queries. Here is an example:

SELECT DISTINCT
    sup.sid
FROM
    Suppliers AS sup
    LEFT OUTER JOIN _Catalog cat ON sup.sid = cat.sid
    INNER JOIN Parts par ON cat.pid = par.pid
WHERE
    sup.address = '221 Packer Ave'
    OR cat.color = 'Red'

What you seem to be missing is the fact that to determine the supplier of a part you need data from all three tables: parts have the color, catalog has the relationship between the supplier and the part and finally the supplier has the SID.

Another solution would be a CTE, which sometimes might perform better (due to different query plan and especially the fact that DISTINCT is not required) but works only with SQL Server 2008R2+:

;WITH CTE_RedPartSuppliers AS (
    SELECT
        cat.sid
    FROM
        Parts par
        INNER JOIN _Catalog cat ON par.pid = cat.pid
    WHERE
        par.color = 'Red'
)

SELECT
    sup.sid
FROM
    Suppliers sup
WHERE
    address = '221 Packer Ave'
    OR EXISTS (
        SELECT 1 FROM CTE_RedPartSuppliers rps WHERE rps.sid = sup.sid
    )
Philip P.
  • 1,162
  • 1
  • 6
  • 15
0

Curious why you cant just do an inner join?

select parts.sid 
from   Suppliers Suppliers inner join parts parts
where  
parts.color = 'Red' 
or     
parts.address = '221 Packer Ave'
CoSpringsGuy
  • 1,615
  • 1
  • 13
  • 16