views:

369

answers:

4

Hi!

I have 2 tables in SQL Server 2005 db with structures represented as such:

CAR: CarID bigint, CarField bigint, CarFieldValue varchar(50);

TEMP: CarField bigint, CarFieldValue varchar(50);

Now the TEMP table is actually a table variable containing data collected through a search facility. Based on the data contained in TEMP, I wish to filter out and get all DISTINCT CarID's from the CAR table exactly matching those rows in the TEMP table. A simple Inner Join works well, but I want to only get back the CarID's that match ALL the rows in TEMP exactly. Basically, each row in TEMP is supposed to be denote an AND filter, whereas, with the current inner join query, they are acting more like OR filters. The more rows in TEMP, the less rows I expect showing in my result-set for CAR. I hope Im making sense with this...if not please let me know and I'll try to clarify.

Any ideas on how I can make this work? Thank u!

+1  A: 

You use COUNT, GROUP BY and HAVING to find the cars that have exactly that many mathicng rows as you expect:

   select CarID
   from CAR c  
   join TEMP t on c.CarField = t.CarField and c.CarFieldValue = t.CarFieldValue
   group by CarID
   having COUNT(*) = <the number you expect>;

You can even make <the number you expect> be a scalar subquery like select COUNT(*) from TEMP.

Remus Rusanu
Hi remus, and thanks 4your response. As with David above, I regret that I had not waited a bit longer before refreshing this page!
Shalan
No worries Shalan
Remus Rusanu
Actually remus, yours makes sense as you've explained it nicely...and with a smaller query! +1
Shalan
+1  A: 
SELECT *
FROM (
SELECT CarID,
COUNT(CarID) NumberMatches
FROM CAR c INNER JOIN
TEMP t ON c.CarField = t.CarField
AND c.CarFieldValue = t.CarFieldValue
GROUP BY CarID
) CarNums
WHERE NumberMatches = (SELECT COUNT(1) FROM TEMP)
astander
WOAH! I didn't expect SO many quick responses! Thank u all for your input. Astander, When I refreshed this page, yours was the only answer, and it works 100%! THANK U. Would u mind explaining it to me so that I can better understand it? I see the added join column criteria (which I didnt think of doing!!!)
Shalan
What i did was as you orininally did. Do the joins, but count the occurances. The compare these occurances to the actual number of entries in the temp table. The COUNT(1) just counts rows in the temp table, you could have used *, or any field/value. Just avoiding looking up fields by using 1
astander
+1  A: 

Hrm...

;WITH FilteredCars
AS
(
  SELECT C.CarId
  FROM Car C
  INNER JOIN Temp Criteria 
     ON C.CarField = Criteria.CarField 
    AND C.CarFieldValue = Critera.CarFieldValue
  GROUP BY C.CarId
  HAVING COUNT(*) = (SELECT COUNT(*) FROM Temp)
)
SELECT *
FROM FilteredCars F
INNER JOIN Car C ON F.CarId = C.CarId

The basic premise is that for ALL criteria to match an INNER JOIN against your temp table must produce as many records as there are within that table. The HAVING clause at the end of the FilteredCars query should widdle the results down to those that match all criteria.

David Andres
Hi David, and thanks for your response! I wish I could mark all 3 as answers, but sadly, I saw Anstander's response first, and immediately tried it out. However, from a readability point, your's is easier to understand.
Shalan
@Shalan: it's all good. I think we all went in the same direction anyway!
David Andres
+1  A: 

Haven't tested this, but I don't think you need a count to do what you want. This query ought to be substantially faster because it avoids a potentially huge number of counts. This query finds all the cars which are missing a value and then filters them out.

select distinct carid from car where carid not in
(
select
  carid
from
  car c
  left outer join temp t on
    c.carfield = t.carfield
    and c.carfieldvalue = t.carfieldvalue
where
  t.carfield is null
)
Abtin Forouzandeh
hi abtin and thanks! actually all rows will have values across all columns. CAR is actually an association table with 2 other tables
Shalan
Ah, I misread the question and didn't realize temp represents the search criteria.
Abtin Forouzandeh