struggling with select with join and where clause - mysql

I'm running some SQL through phpmyadmin. I'm trying to do a query with 2 tables. The first xlsws_product has all the product info the second xlsws_category_assn contains two columns one with category id and the other with product id. The category names are in a third table but I don't need them for this.
What I am looking to do is select the rows from the product table that are in the categories with id 210, 218 and 370. This is what I tried so far:
SELECT *
FROM xlsws_product
JOIN xlsws_product_category_assn ON xlsws_product.id = xlsws_product_category_assn.product_id
WHERE
xlsws_product_category_assn.category_id = '210' OR '218' OR '370'`
The result for this gave me 24090 rows from a bunch of categories and there should only by a handful of rows in those categories. What's bizarre here is that there are 56474 rows in the product table so I'm not sure how the results are being filtered.
Just for the hell of it I tried limiting my query to just one category id with the following query:
SELECT *
FROM xlsws_product
JOIN xlsws_product_category_assn ON xlsws_product.id = xlsws_product_category_assn.product_id
WHERE xlsws_product_category_assn.category_id = '210'
This yielded zero rows...
I'm sure there is something simple I am missing but after spending a while searching for a solution I just can't figure it out. Thanks for the help.

If you need to find all the data which are in the category '210' OR '218' OR '370'
You can do as
SELECT * FROM
xlsws_product xp
JOIN xlsws_product_category_assn xpc ON xp.id = xpc.product_id
WHERE
xpc.category_id in (210,218,370)
If you need to find the products which have all the 3 given category you can do as
SELECT * FROM
xlsws_product xp
JOIN xlsws_product_category_assn xpc ON xp.id = xpc.product_id
WHERE
xpc.category_id in (210,218,370)
group by xp.id having count(*) = 3

Related

Duplicate results with SQL Query join between 2 tables

I'm trying to join 2 tables with the following query:
SELECT board.boardID, board.userID, board.postID, items.Url,
items.Image
FROM board
JOIN items on userID = items.user_id
Which gives me the following result:
However, as you can see, every result is printed double. I tried using SELECT DISTINCT but that is giving the same result.
My mistake,
The query I was looking for is:
SELECT DISTINCT board.boardID, board.userID, board.postID, items.Url,
items.Image
FROM board
JOIN items on postID = items.id
I joined the items table on the wrong id :)

MySQL getting count of a related table

My SQL's more than a little rusty, and I'm having trouble getting this to work, so any assistance would be greatly appreciated.
I've got three tables:
sessions
---------------
id
session_visits
---------------
id | session_id
searches
---------------
id | session_visit_id
And I want to get a list of all sessions with the total visits and searches for each sessions, which is linked by the session_visits table. I can get the visits fine, but am having trouble getting the total of searches for each session too.
So far I've got
SELECT *,(SELECT Count(*)
FROM session_visits
WHERE session_id = sessions.id) AS num_visits,
(SELECT Count(*)
FROM searches
WHERE session_visit_id = (SELECT * FROM session_visits
WHERE session_id = sessions.id)) AS total_searches
FROM sessions
Which is failing on every count! Am I going about this the right way or am I fundamentally doing it wrong?
You can do this in one query, by joining the 3 tables together, and then use aggregates COUNT DISTINCT (to eliminate duplicated) and COUNT to get the total number of rows for the child and grandchild rows respectively, grouped by the Sessionid.
SELECT s.id AS SessionId, COUNT(DISTINCT sv.id) AS SessionVisits, COUNT(sr.ID) AS Searches
FROM sessions s
LEFT JOIN session_visits sv
ON s.id = sv.session_id
LEFT JOIN searches sr
ON sr.session_visit_id = sv.id
GROUP BY s.id;
SqlFiddle here
(Edit : Changed to left outer joins to handle scenarios where there are no visits for session, or no searches per visit)
query generates error because of column name is not mentioned in query
Operand should contain 1 column
and try with IN

MYSQL select results from 3 tables with an array of ids

Ok, so I have 3 mysql tables where I need to extract data from. Anything to do with joins really gets me stuck!
Table 1 = products (productid, name)
Table 2 = category (categoryid, name)
Table 3 = categoryproduct (categoryid, productid) - my join table
I have an array of product ids which I need to get a random selection of products that fall into the same categories as these products.
The idea is that the results of the query will display a section in my cart of similar/related products that the customer may like
So something like
SELECT name etc FROM table1
WHERE table2.categoryid of results of the query = table3.categoryid of current products
ORDER BY RAND()
LIMIT 3
How do I write that??
Assuming you're using PHP, following method will fetch 10 related products from database.
$productids = array(1002,789,999,203,321);
$sql = '
SELECT * FROM
products p JOIN categoryproduct pc
ON p.productid = pc.productid
WHERE pc.categoryid IN(
SELECT DISTINCT(categoryid) FROM
products inner_p JOIN categoryproduct inner_pc
ON inner_p.productid = inner_pc.productid
WHERE inner_p.productid IN('.implode(',',$productids).')
)
ORDER BY RAND()
LIMIT 10';
If i have understood your problem correctly then this query may help. Here instead of subquery you can give comma separated string which contains categoryid of different products selected by the user.
select p.name
from products p,categoryproduct cp
where p.productid=cp.productid
and cp.categorid in(
select categoryid
from cartitems)
order by RAND()

Select row dependent on other rows in the table

Apologies if this has been asked before but I really didn't know what to search and thus not sure how to word the question title so fingers crossed.
I'm building quite a common system where one product can have multiple categories and on the front-end, the user can search for products specifying multiple categories.
Say we had the following schema and data ( I cant post images yet, apologies, please see link )-
table name: product_categories
Data:
The products table is very standard - id, name, amount etc.
So product 1 has 2 categories.
If the user checks 2 tickboxes on the search page which represent category 2 and 3, how would I query that so only products which have both of those categories come back?
Something such as follows doesn't work, as there is no one row in that which has a category id of 2 AND a category id of 3:
SELECT * from product_categories where `category_id` = 2 AND `category_id` = 3;
I've tried using WHERE IN aswell, however, this would return product 1 even if i was looking for products which had both category id 2 and 6 ( for example ) which I don't want.
This is part of a bigger query however, I will be able to apply the solution if I manage to find one.
Something along this way should work
SELECT * FROM products WHERE
EXISTS (SELECT * FROM product_categories
WHERE product_id = products.id AND category_id = 2)
AND
EXISTS (SELECT * FROM product_categories
WHERE product_id = products.id AND category_id = 3)
...
Other solution is to generate JOIN for each category.
SELECT * FROM products
JOIN product_categories AS cs1 ON cs1.product_id = products.id
AND cs1.category_id = 2
JOIN product_categories AS cs2 ON cs2.product_id = products.id
AND cs2.category_id = 3
...
Unless you expect product_categories to be bigger than tens of millions of rows, both solutions should work reasonably, if correct indexes are created.
I think you need to use a sub-query here:
SELECT * from product_categories where id IN (SELECT id from product_categories where `category_id` = 2) AND IN (SELECT id from product_categories where `category_id` = 3)
I am not 100% sure this works (long time since I worked with SQL)
Many thanks for the suggestions guys, much appreciated. I think found a solution, this seems to produce the expected results but I'll be writing some more Unit Tests around my method to ensure it works.
The solution I found is as follows:
select * from products_categories where category_id in (2,3) HAVING count(distinct(id)) = 2
So this uses WHERE IN, however, using HAVING, it then checks the count of unique records returned and ensures it's equal to the amount of categories provided.
Cheers,
Darren

MySQL join with 3 tables trick

I can't obtain the result I want, let me explain:
I have two tables :
CATEGORIES
PROJECTS
and between them another table which makes the link:
ASSIGNED_CAT with 2 columns: PROJECT_ID and CATEGORY_ID
In ASSIGNED_CAT I get the IDs of CATEGORIES and PROJECTS linked together.
Now I need to get the CATEGORIES which contains PROJECTS and if not don't show them.
Example:
If CATEGORY 1 have projects display the CATEGORY NAME and if not don't show.
Any idea to trick this? I've tried many SQL JOIN without success.
I guess you are missing the EXISTS clause.
The following query selects all categories, for which at least one row exists in the intersection table.
SELECT category_name
FROM categories c
WHERE EXISTS (
SELECT 1
FROM assigned_cat ac
WHERE ac.category_id = c.category_id
)