all groups > sql server data mining > november 2003 >
The scenario: two tables CustomerTable --------------- CustomerID OrderID CustomerName CustomerEmail CustomerPhone OrderTable --------------- OrderID ProductID ProductName ProductCost This database was handed to me and I was asked to solve a problem - it looks like an inner join solution would apply, but I'm not 100% sure. There are 14 products total (numbers 1 through 14). I'm looking to get a list of all the customers who have ordered product #1, UNLESS they've ordered product #14 in which case I don't want to know about that customer at all. Any help would be greatly appreciated! I'll watch the newsgroup for the answer - hopefully your response can help someone else too. However, if you prefer to email me directly, you can send it to me at bunchah at yahoo dot com. Thanks in advance! (if it'll help, I'll buy the person offering the correct solution a beer - pending age verification of course) ;) -Al
On Sat, 22 Nov 2003 00:52:35 GMT, "news-east.earthlink.net" [quoted text, click to view] <abunch.goawayspammer@yahoo.nospam.com> wrote: >The scenario: > >two tables > >CustomerTable >--------------- >CustomerID >OrderID >CustomerName >CustomerEmail >CustomerPhone > >OrderTable >--------------- >OrderID >ProductID >ProductName >ProductCost > >This database was handed to me and I was asked to solve a problem - it looks >like an inner join solution would apply, but I'm not 100% sure. > >There are 14 products total (numbers 1 through 14). >I'm looking to get a list of all the customers who have ordered product #1, >UNLESS they've ordered product #14 in which case I don't want to know about >that customer at all.
A literal translation could be: SELECT DISTINCT CustomerID FROM CustomerTable WHERE CustomerID IN (SELECT CustomerID FROM OrderTable WHERE ProductID = 1) AND CustomerID NOT IN (SELECT CustomerID FROM OrderTable WHERE ProductID = 14) Or: SELECT CustomerID FROM CustomerTable INNER JOIN OrderTable USING (OrderID) WHERE ProductID = 1 MINUS SELECT CustomerID FROM CustomerTable INNER JOIN OrderTable USING (OrderID) WHERE ProductID = 14 -- Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk)
select ct.customerid from CustomerTable ct join OrderTable ot on ct.orderid = ot.orderid group by ct.customerid having (count(case ot.productid when 1 then 1 else null end) > 0) and (count(case ot.productid when 14 then 1 else null end) = 0) order by ct.customerid HTH, Dave "news-east.earthlink.net" <abunch.goawayspammer@yahoo.nospam.com> wrote in message news:nryvb.13979$Wy4.3214@newsread2.news.atl.earthlink.net... [quoted text, click to view] > The scenario: > > two tables > > CustomerTable > --------------- > CustomerID > OrderID > CustomerName > CustomerEmail > CustomerPhone > > OrderTable > --------------- > OrderID > ProductID > ProductName > ProductCost > > This database was handed to me and I was asked to solve a problem - it looks > like an inner join solution would apply, but I'm not 100% sure. > > There are 14 products total (numbers 1 through 14). > I'm looking to get a list of all the customers who have ordered product #1, > UNLESS they've ordered product #14 in which case I don't want to know about > that customer at all. > > Any help would be greatly appreciated! I'll watch the newsgroup for the > answer - hopefully your response can help someone else too. However, if you > prefer to email me directly, you can send it to me at bunchah at yahoo dot > com. > > Thanks in advance! > > (if it'll help, I'll buy the person offering the correct solution a beer - > pending age verification of course) ;) > > -Al > > > >
[quoted text, click to view] "Andy Hassall" <andy@andyh.co.uk> wrote in message news:t5dtrvg8di6hfjirhpttt853pc733cqhhm@4ax.com... > On Sat, 22 Nov 2003 00:52:35 GMT, "news-east.earthlink.net" > <abunch.goawayspammer@yahoo.nospam.com> wrote: > > >The scenario: > > > >two tables > > > >CustomerTable > >--------------- > >CustomerID > >OrderID > >CustomerName > >CustomerEmail > >CustomerPhone > > > >OrderTable > >--------------- > >OrderID > >ProductID > >ProductName > >ProductCost > > > >This database was handed to me and I was asked to solve a problem - it looks > >like an inner join solution would apply, but I'm not 100% sure. > > > >There are 14 products total (numbers 1 through 14). > >I'm looking to get a list of all the customers who have ordered product #1, > >UNLESS they've ordered product #14 in which case I don't want to know about > >that customer at all. > > A literal translation could be: > > SELECT DISTINCT CustomerID > FROM CustomerTable > WHERE CustomerID IN (SELECT CustomerID > FROM OrderTable > WHERE ProductID = 1) > AND CustomerID NOT IN (SELECT CustomerID > FROM OrderTable > WHERE ProductID = 14) > > Or: > > SELECT CustomerID > FROM CustomerTable > INNER JOIN OrderTable USING (OrderID) > WHERE ProductID = 1 > MINUS > SELECT CustomerID > FROM CustomerTable > INNER JOIN OrderTable USING (OrderID) > WHERE ProductID = 14
Andy, I don't think the second solution will work. First of all, MINUS is not supported on SQL Server. Second, even if this is run on Oracle, the two result sets you're performing the minus on are the joined tables, not the single table CustomerTable. So the two sets are disjoint because ProductID cannot be 1 and 14 simultaneously. So you'll end up with all the customers who have ordered product #1, regardless of whether they have ordered product #14 or not. Since there's a beer involved here, I have to be a bit particular... ;-) - Dave [quoted text, click to view] > > -- > Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk) > Space: disk usage analysis tool ( http://www.andyhsoftware.co.uk/space)
[quoted text, click to view] "Dave Hau" <nospam_dave_nospam_123@nospam_netscape_nospam.net_nospam> wrote in message news:r%yvb.35000$gZ7.19519@newssvr27.news.prodigy.com... > "Andy Hassall" <andy@andyh.co.uk> wrote in message > news:t5dtrvg8di6hfjirhpttt853pc733cqhhm@4ax.com... > > On Sat, 22 Nov 2003 00:52:35 GMT, "news-east.earthlink.net" > > <abunch.goawayspammer@yahoo.nospam.com> wrote: > > > > >The scenario: > > > > > >two tables > > > > > >CustomerTable > > >--------------- > > >CustomerID > > >OrderID > > >CustomerName > > >CustomerEmail > > >CustomerPhone > > > > > >OrderTable > > >--------------- > > >OrderID > > >ProductID > > >ProductName > > >ProductCost > > > > > >This database was handed to me and I was asked to solve a problem - it > looks > > >like an inner join solution would apply, but I'm not 100% sure. > > > > > >There are 14 products total (numbers 1 through 14). > > >I'm looking to get a list of all the customers who have ordered product > #1, > > >UNLESS they've ordered product #14 in which case I don't want to know > about > > >that customer at all. > > > > A literal translation could be: > > > > SELECT DISTINCT CustomerID > > FROM CustomerTable > > WHERE CustomerID IN (SELECT CustomerID > > FROM OrderTable > > WHERE ProductID = 1) > > AND CustomerID NOT IN (SELECT CustomerID > > FROM OrderTable > > WHERE ProductID = 14) > > > > Or: > > > > SELECT CustomerID > > FROM CustomerTable > > INNER JOIN OrderTable USING (OrderID) > > WHERE ProductID = 1 > > MINUS > > SELECT CustomerID > > FROM CustomerTable > > INNER JOIN OrderTable USING (OrderID) > > WHERE ProductID = 14 > > Andy, I don't think the second solution will work. First of all, MINUS is > not supported on SQL Server. Second, even if this is run on Oracle, the two > result sets you're performing the minus on are the joined tables, not the > single table CustomerTable. So the two sets are disjoint because ProductID > cannot be 1 and 14 simultaneously. So you'll end up with all the customers > who have ordered product #1, regardless of whether they have ordered product > #14 or not.
Sorry didn't notice you're selecting only CustomerID instead of *. It does work. My bad. You won the beer. :) - Dave [quoted text, click to view] > > Since there's a beer involved here, I have to be a bit particular... ;-) > > - Dave > > > > > > -- > > Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk) > > Space: disk usage analysis tool ( http://www.andyhsoftware.co.uk/space) > >
SELECT DISTINCT cart_id FROM OrderTable WHERE cart_id IN ( SELECT cart_id FROM CartTable WHERE product_index =1 ) AND cart_id NOT IN ( SELECT cart_id FROM CartTable WHERE product_index =14 ) After I switched the fields and table names out to match the real table names ( they were confusing the issue a bit) I tried the quer(y/ies) and I get errors on both. Maybe I should clarify - this is running in a MySQL database server - though with straight SQL I would think this wouldn't matter much, no? I moved the structure of the actual tables to a database on my home server and punched a hole in my firewall to allow you to look at this first hand - mind you, there are only a few records and they're made up, but they should be sufficient enough to let you tinker... surf to http://maple.homelinux.com/phpmyadmin/index.php account : aaron pass: pass123 I'll leave it up and running this evening - the account has limited rights (to that database only)... take a gander? BTW - for the speedy response, I'll buy both of you guys a beer...name your poison! [quoted text, click to view] "Andy Hassall" <andy@andyh.co.uk> wrote in message news:t5dtrvg8di6hfjirhpttt853pc733cqhhm@4ax.com... > On Sat, 22 Nov 2003 00:52:35 GMT, "news-east.earthlink.net" > <abunch.goawayspammer@yahoo.nospam.com> wrote: > > >The scenario: > > > >two tables > > > >CustomerTable > >--------------- > >CustomerID > >OrderID > >CustomerName > >CustomerEmail > >CustomerPhone > > > >OrderTable > >--------------- > >OrderID > >ProductID > >ProductName > >ProductCost > > > >This database was handed to me and I was asked to solve a problem - it looks > >like an inner join solution would apply, but I'm not 100% sure. > > > >There are 14 products total (numbers 1 through 14). > >I'm looking to get a list of all the customers who have ordered product #1, > >UNLESS they've ordered product #14 in which case I don't want to know about > >that customer at all. > > A literal translation could be: > > SELECT DISTINCT CustomerID > FROM CustomerTable > WHERE CustomerID IN (SELECT CustomerID > FROM OrderTable > WHERE ProductID = 1) > AND CustomerID NOT IN (SELECT CustomerID > FROM OrderTable > WHERE ProductID = 14) > > Or: > > SELECT CustomerID > FROM CustomerTable > INNER JOIN OrderTable USING (OrderID) > WHERE ProductID = 1 > MINUS > SELECT CustomerID > FROM CustomerTable > INNER JOIN OrderTable USING (OrderID) > WHERE ProductID = 14 > > -- > Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk) > Space: disk usage analysis tool ( http://www.andyhsoftware.co.uk/space)
On Sat, 22 Nov 2003 01:50:17 GMT, "news-east.earthlink.net" [quoted text, click to view] <abunch.goawayspammer@yahoo.nospam.com> wrote: >Newsgroups: alt.php.sql,comp.databases.ms-sqlserver,microsoft.public.sqlserver.datamining > >SELECT DISTINCT cart_id >FROM OrderTable >WHERE cart_id >IN ( >SELECT cart_id >FROM CartTable >WHERE product_index =1 ) AND cart_id NOT >IN ( >SELECT cart_id >FROM CartTable >WHERE product_index =14 ) > >After I switched the fields and table names out to match the real table >names ( they were confusing the issue a bit) I tried the quer(y/ies) and I >get errors on both.
What errors? [quoted text, click to view] >Maybe I should clarify - this is running in a MySQL database server - though >with straight SQL I would think this wouldn't matter much, no?
It makes a big difference - MySQL has large gaps in its SQL syntax - in particular, no subqueries or set operations (i.e. MINUS). (Subqueries are going into the alpha 4.1 version, I think UNION went into 4.0 at some point, don't know about MINUS). [quoted text, click to view] >I moved the structure of the actual tables to a database on my home server >and punched a hole in my firewall to allow you to look at this first hand - >mind you, there are only a few records and they're made up, but they should >be sufficient enough to let you tinker... > >surf to http://maple.homelinux.com/phpmyadmin/index.php >account : aaron >pass: pass123 404 Object not found. A variation on Dave's query to account for MySQL's limitations and quirks (identifiers case-sensitive, cannot reference aggregates in HAVING clauses only their aliases, JOIN must be INNER JOIN) comes up with: select ct.CustomerID, count(case ot.ProductID when 1 then 1 else null end) num_1, count(case ot.ProductID when 14 then 1 else null end) num_14 from CustomerTable ct inner join OrderTable ot on (ct.OrderID = ot.OrderID) group by ct.CustomerID having num_1 > 0 and num_14 = 0 order by ct.CustomerID This works against MySQL 3.x, 'cos I just ran it. -- Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk)
[quoted text, click to view] "Andy Hassall" <andy@andyh.co.uk> wrote in message news:duhtrvg02q0224s2peoa2cb7s99h868ao4@4ax.com... > On Sat, 22 Nov 2003 02:06:15 +0000, Andy Hassall <andy@andyh.co.uk> wrote: > > > A variation on Dave's query to account for MySQL's limitations and quirks > >[...] cannot reference aggregates in HAVING clauses only > >their aliases, [...] > > OK, that's wrong, looks like I was thinking of something else. So going closer > back to Dave's query: > > select DISTINCT ct.CustomerID > from CustomerTable ct > inner join OrderTable ot > on (ct.OrderID = ot.OrderID) > group by ct.CustomerID > having count(case ot.ProductID when 1 then 1 else null end) > 0 > and count(case ot.ProductID when 14 then 1 else null end) = 0 > order by ct.CustomerID;
IMHO, no need for the DISTINCT. The "group by ct.CustomerID" will always give you distinct values of CustomerID. - Dave [quoted text, click to view] > > -- > Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk) > Space: disk usage analysis tool ( http://www.andyhsoftware.co.uk/space)
[quoted text, click to view] On Sat, 22 Nov 2003 02:06:15 +0000, Andy Hassall <andy@andyh.co.uk> wrote: > A variation on Dave's query to account for MySQL's limitations and quirks >[...] cannot reference aggregates in HAVING clauses only >their aliases, [...]
OK, that's wrong, looks like I was thinking of something else. So going closer back to Dave's query: select DISTINCT ct.CustomerID from CustomerTable ct inner join OrderTable ot on (ct.OrderID = ot.OrderID) group by ct.CustomerID having count(case ot.ProductID when 1 then 1 else null end) > 0 and count(case ot.ProductID when 14 then 1 else null end) = 0 order by ct.CustomerID; -- Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk)
On Sat, 22 Nov 2003 02:23:14 GMT, "Dave Hau" [quoted text, click to view] <nospam_dave_nospam_123@nospam_netscape_nospam.net_nospam> wrote: >> select DISTINCT ct.CustomerID [snip] >> group by ct.CustomerID
[snip] [quoted text, click to view] >IMHO, no need for the DISTINCT. The "group by ct.CustomerID" will always >give you distinct values of CustomerID.
Ah, yes - that's true. -- Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk)
select DISTINCT ct.cart_id from OrderTable ct inner join CartTable ot on (ct.cart_id = ot.cart_id) group by ct.cart_id having count(case ot.product_index when 1 then 1 else null end) > 0 and count(case ot.product_index when 14 then 1 else null end) = 0 order by ct.cart_id; Thanks Andy, that worked PERFECTLY! Ok, now what kind of beer do you drink? (or wine?) Dave - thanks to you too - it's nice to know I'm not the only one working on a Friday night. :) -Al [quoted text, click to view] "Andy Hassall" <andy@andyh.co.uk> wrote in message news:duhtrvg02q0224s2peoa2cb7s99h868ao4@4ax.com... > On Sat, 22 Nov 2003 02:06:15 +0000, Andy Hassall <andy@andyh.co.uk> wrote: > > > A variation on Dave's query to account for MySQL's limitations and quirks > >[...] cannot reference aggregates in HAVING clauses only > >their aliases, [...] > > OK, that's wrong, looks like I was thinking of something else. So going closer > back to Dave's query: > > select DISTINCT ct.CustomerID > from CustomerTable ct > inner join OrderTable ot > on (ct.OrderID = ot.OrderID) > group by ct.CustomerID > having count(case ot.ProductID when 1 then 1 else null end) > 0 > and count(case ot.ProductID when 14 then 1 else null end) = 0 > order by ct.CustomerID; > > -- > Andy Hassall (andy@andyh.co.uk) icq(5747695) ( http://www.andyh.co.uk) > Space: disk usage analysis tool ( http://www.andyhsoftware.co.uk/space)
Off the top of my head how about something like this. select a.[CustomerID], max( b.[ProductID] ) as [MaxProductID], min( b.[ProductID] ) as [MinProductID] from CustomerTable a inner join OrderTable b on a.[OrderID] = b.[OrderID] group by a.[CustomerID] having min( b.[ProductID] ) = 1 and max( b.[ProductID] ) < 14 Chris. "news-east.earthlink.net" <abunch.goawayspammer@yahoo.nospam.com> wrote in message news:nryvb.13979$Wy4.3214@newsread2.news.atl.earthlink.net... [quoted text, click to view] > The scenario: > > two tables > > CustomerTable > --------------- > CustomerID > OrderID > CustomerName > CustomerEmail > CustomerPhone > > OrderTable > --------------- > OrderID > ProductID > ProductName > ProductCost > > This database was handed to me and I was asked to solve a problem - it looks > like an inner join solution would apply, but I'm not 100% sure. > > There are 14 products total (numbers 1 through 14). > I'm looking to get a list of all the customers who have ordered product #1, > UNLESS they've ordered product #14 in which case I don't want to know about > that customer at all. > > Any help would be greatly appreciated! I'll watch the newsgroup for the > answer - hopefully your response can help someone else too. However, if you > prefer to email me directly, you can send it to me at bunchah at yahoo dot > com. > > Thanks in advance! > > (if it'll help, I'll buy the person offering the correct solution a beer - > pending age verification of course) ;) > > -Al > > > >
[quoted text, click to view] "news-east.earthlink.net" <abunch.goawayspammer@yahoo.nospam.com> wrote in message news:<nryvb.13979$Wy4.3214@newsread2.news.atl.earthlink.net>... > The scenario: > > two tables > > CustomerTable > --------------- > CustomerID > OrderID > CustomerName > CustomerEmail > CustomerPhone > > OrderTable > --------------- > OrderID > ProductID > ProductName > ProductCost > > This database was handed to me and I was asked to solve a problem - it looks > like an inner join solution would apply, but I'm not 100% sure. > > There are 14 products total (numbers 1 through 14). > I'm looking to get a list of all the customers who have ordered product #1, > UNLESS they've ordered product #14 in which case I don't want to know about > that customer at all. > > Any help would be greatly appreciated! I'll watch the newsgroup for the > answer - hopefully your response can help someone else too. However, if you > prefer to email me directly, you can send it to me at bunchah at yahoo dot > com. > > Thanks in advance! > > (if it'll help, I'll buy the person offering the correct solution a beer - > pending age verification of course) ;) > > -Al
Hi , Here is my reply select customertable.* c1 from customertable inner join ordertable o1 on c1.orderid = o1.orderid where c1.orderid = 1 and o1.orderid <> 14 With Thanks
Don't see what you're looking for? Try a search.
|
|
|