tags:

views:

132

answers:

6

I have 3 tables as follows.

salesman(sid,sname)
location(lid,lname)
sales_loc(sid,lid)

Now i want to print the sid and sname of saleman who has visited all locations. I want a SQL query and I don't want a PL/SQL code.

+7  A: 
select sid, sname from salesman
where not exists 
        (select 1 from location
          where not exists
                  (select 1 from sales_loc
                    where sid=saleman.sid 
                     and lid = location.lid));
ammoQ
Oookay, that's an interesting one. Never really thought about that you could negate the statement; nice.
Joey
Yeah, I'm still trying to wrap my head around it :)
Lewisham
Lewisham: I've been everywhere when there is no location where i haven't been.
ammoQ
can u gisribe ur logic?
+3  A: 

Another approach:

select sid, sname from salesman
where
  (select count(*) from location) =
  (select count(*) from sales_loc where sales_loc.sid = salesman.sid)

Edit: In case sales_loc(sid,lid) pair isn't a key, the below query is more appropriate,
as ammoQ suggested:

select sid, sname from salesman
where
  (select count(*) from location) =
  (select count(distinct lid) from sales_loc where sales_loc.sid = salesman.sid)
Nick D
human readable :)
Amarghosh
*sigh* snap... =)
Will
+1, although it makes some assumptions; I'd make the second subquery a "select count(distinct lid) ..." so it still works when there is more than one entry in sales_loc for a salesman and a location
ammoQ
@ammoQ, you are right. I made that assumption. I'll edit my answer to include your suggestion.
Nick D
A: 

Get all salesman recs where number of locations visited equals number of locations.

select sm.* from salesman as sm
where (select count(sl.*) from sales_loc as sl where sl.sid = sm.sid)
 = (select count(l.*) from location as l);
Will
A: 

One more for the pot!

Given these salesmen and their territories ...

SQL> select s.sname, l.lname
  2  from   salesman s
  3         , location l
  4         , sales_loc sl
  5  where  sl.sid = s.sid
  6  and sl.lid = l.lid
  7  order by s.sid, l.lid
  8  /

SNAME      LNAME
---------- ----------
FOX        TRAIN
FOX        BOAT
KNOX       BOAT
KNOX       HOUSE
SAM        TRAIN
SAM        BOAT
SAM        HOUSE

7 rows selected.

SQL>

... this query extracts the one who has visited all of them...

SQL> select s.sname
  2  from   salesman s
  3  where s.sid not in  (
  4      select sid from (
  5          select cjs.sid, cjl.lid
  6          from   salesman cjs
  7                 cross join location cjl
  8          minus
  9          select sl.sid, sl.lid
 10          from   sales_loc sl
 11      )
 12  )
 13  /

SNAME  
------ ----
SAM

SQL>
APC
Anyone using this query in sqlserver should change minus to except.
Colour Blend
You should also attach an alias to the second select statement. select ss.sid from (...)
Colour Blend
A: 

This should work. I've tried it out.

select a.sid, a.salesman, count(a.sid) as total from salesman a
inner join sales_loc b on b.sid = a.sid
inner join location c on c.lid = b.lid
group by a.sid, a.salesman
having count(a.sid) = (select count(*) from location)

It uses the total number of locations to compare.

Colour Blend
A: 

salesman(sid,sname) location(lid,lname) sales_loc(sid,lid)

select s.sid,s.sname from salesman s,location l, sales_loc sl where s.sid=sl.sid and l.lid=sl.lid

P Sharma