views:

83

answers:

5

I'd like to find the hits and misses in a table using only a list of items without having to create a new table to contain the list items and without using any scripting. I do many ad-hoc queries throughout the day so this would be useful.

Here's an example of what I'm using now:

SELECT custid, name, email  
FROM customers  
WHERE custid IN  
('1111', '2222', '3333', '4444')  

This returns all the entries in customers table where the customer IDs match the one in the list I provide.

I'd like to find a way to return results like an OUTER JOIN, where I could see the matches as well as the misses.

FYI: I'm using MS SQL Server but it would be useful to be able to do this in mySQL as well. Thanks!

A: 

This would probably work. I'm using the table #test in place of your customers table and populating it with 1, 3 and 5. Then I'm searching for 1, 2 and 3.

CREATE TABLE #test 
(
    id int
)
GO

INSERT INTO #test
SELECT 1 UNION SELECT 3 UNION SELECT 5
GO

SELECT *
FROM ( SELECT 1 AS id UNION SELECT 2 UNION SELECT 3 ) s
LEFT OUTER JOIN #test t ON s.id=t.id

Here's an example using your customers table:

SELECT s.SearchId, c.custid, c.name, c.email
FROM ( SELECT '1111' AS SearchId UNION SELECT '2222' 
    UNION SELECT '3333' UNION SELECT '4444' ) s
LEFT OUTER JOIN customers c ON s.SearchId=c.custid
csm8118
+3  A: 

There are several ways to do this. Here are two:

SELECT C1.custid, name, email, C2.CustID As Match FROM customers As C1 left join (SELECT custid FROM customers
WHERE custid IN
('1111', '2222', '3333', '4444')) As C2 on C1.custid=C2.custid

There will be a number (one of the 4) in the Match column if it's one of the numbers. Or:

SELECT custid, name, email, Case When custid in ('1111', '2222', '3333', '4444') Then 'Match' Else '' End As IsMatch FROM customers

The IsMatch column will say "Match" if it's one of the four values.

The second one will usually be faster.

Patrick Karcher
String literals use single quotes.
Joey
The second option sort of works. Unfortunately, the query checks against ALL the entries in the customers table - not just the ones in the list. So, I get more data back than I need. In the case I'm looking at our customers table would have 200k+ records so it's not helpful return all those records to find 4 matches. Thanks though!
Don
I don't understand, doesn't your question say you WANT to see all the records, matching or not?
Ben Marini
Only the records in the list I provide. So, I would be looking for an output like this: 1111 smith [email protected] 2222 null null 3333 roberts [email protected] 4444 null null I want to limit the returned data set to just those custids in the list I provide - not everything in the table.I hadn't ever used the CASE function so that was helpful but I think I might have to go the way of using a temp table.
Don
Yes, in your question you say you want it to show *hits and misses* and that you want it to be *like an outer join*; so I show how to achieve that end. Of course you'll need to tweak these queries to your purposes, include adding filtering in the where clause. My examples were based on your example. (which was well formulated actually, deserves upvote.)
Patrick Karcher
So, the `In ('1111', etc.` is what you want filtered on. Then, what do you want to left join against? You original query will work just as you wish. Or, are *name* and *email* on a different table? Then do a left join on that table. I'm missing something. Can you clarify?
Patrick Karcher
A: 

Use a user-defined function to generate a table from a comma-separated list of values. Then you can do an outer join to the list, like this:

select customers.custid, name, email
  from customers
    left outer join dbo.get_id_table('1111', '2222', '3333', '4444') as ids
      on (customers.custid = ids.custid)

There are several versions of a 'get_id_table' type function posted here and elsewhere on the web (sorry - I can't come up with a link right now).

Ray
In the end (in the interest of time, really), I created a function to parse a delimited list of items and place them into a temp table (similar to http://articles.techrepublic.com.com/5100-10878_11-5796615.html). This way I can do the outer join on that. Thanks!
Don
A: 

You want you to put your custids that you a searching for in a table and join like so...

CREATE TABLE #temp
(
    custid varchar(4)
)

INSERT INTO #temp(employeeid) VALUES '1111'
INSERT INTO #temp(employeeid) VALUES '2222'
INSERT INTO #temp(employeeid) VALUES '3333'
INSERT INTO #temp(employeeid) VALUES '4444'

SELECT c.custid, name, email, t.custid  
FROM customers c
LEFT JOIN #temp t ON c.custid = t.custid
ctrlShiftBryan
I'd prefer to not have to create any new or temp tables.
Don
A: 

SQL server 2005, 2008

DECLARE @tmp TABLE (id varchar(8))

INSERT INTO @tmp ( id )
SELECT  '1111' UNION
SELECT  '2222' UNION
SELECT  '3333' UNION
SELECT  '4444' ;

SELECT c.custid, c.name, c.email  
FROM customers AS c
LEFT JOIN @tmp AS t ON t.id = customers.custid
Damir Sudarevic