October 21, 2005 at 11:15 am
Hi,
I have two tables, Customer (customerid, name) and Subscription (magazineid, customerid). I have a page where users can search for customers who have subscribed for selected magazines. Say there are 5 magazines, user can select magazine 1 and 3 and hit search, I return all the users who have subscribed for magazine 1 and 3. The way I am doing it is, pass the magazine ids as a comma seperated string. In the stored procedure I split the string and for each magazine id I make sure the customerid exists.
SELECT customerid, name FROM customers cs
WHERE EXISTS (SELECT * FROM subcriptions sub where sub.customerid = cs.customerid and sub.magazine = 1)
AND EXISTS (SELECT * FROM subcriptions sub where sub.customerid = cs.customerid and sub.magazine = 3)
Is there any way to simplify this query. There are lots of customers and around 30 subscriptions. This is actually a part of a larger query.
Thanks.
October 21, 2005 at 11:29 am
Two possible approaches might be:
SELECT customerid, name
FROM customers cs
WHERE EXISTS( SELECT *
FROM subcriptions sub
WHERE sub.customerid = cs.customerid
AND sub.magazine IN( 1, 3))
SELECT customerid, name
FROM customers cs
INNER JOIN( SELECT sub.customerid
FROM subcriptions sub
WHERE sub.magazine IN( 1, 3)) ON( sub.customerid = cs.customerid)
I wasn't born stupid - I had to study.
October 21, 2005 at 11:31 am
Well, the result should contain customers who have subscribed for both 1 and 3. If we use IN, won't the result cotains customers who have subscribed for either 1 or 3?
October 21, 2005 at 11:36 am
Repeating multiple EXISTS for a large number of potential parameters isn't really necessary if you know the number of magazine parameters passed in. All you need to do is count the subscriptions in 1 derived table and only select the records where the count matches.
Assuming you have stored the result of parsing your comma separated params in a variable called @NumberParams, this should work:
SELECT customerid, name
FROM customers cs
INNER JOIN
(
SELECT customerid, Count(*) As NumberSubscribed
FROM subcriptions
WHERE magazine IN (1,3)
GROUP BY customerid
) dt
ON cs.customerid = dt.customerid
WHERE dt.NumberSubscribed = @NumberParams
October 21, 2005 at 11:36 am
Your original post does imply that - sorry.
You can just add an AND to my suggestion(s):
WHERE sub.magazine = 1
AND sub.magazine = 3
I wasn't born stupid - I had to study.
October 21, 2005 at 11:42 am
Also, your requirements didn't mention what to return in the above example for a customer who subscribes to, say, magazines 1, 3 and 4 ?
If you pass 1 & 3, do you want to return customers who subscribe ONLY to 1 & 3, or customers who subscribe to AT LEAST 1 & 3 and possibly some others.
October 21, 2005 at 11:46 am
MUCH better solution and excellent question!
Thanks PW.
I wasn't born stupid - I had to study.
October 21, 2005 at 12:02 pm
"If you pass 1 & 3, do you want to return customers who subscribe ONLY to 1 & 3, or customers who subscribe to AT LEAST 1 & 3 and possibly some others."
Customers who subscribe to atleast 1 and 3.
Viewing 8 posts - 1 through 7 (of 7 total)
You must be logged in to reply to this topic. Login to reply