joining 3 tables in one sql - mysql

I have 3 tables as described below ,
table1 'ads'
id userid
1 47
2 47 //ads.id = adcat.adid
3 45
4 47
table2 'adcat'
adid catid
1 1
2 3
3 3 // adcat.catid = categories.id
4 3
table3 'categories'
id name
1 mathematic
2 biolog
3 leteratur
4 chemi
What I want is to get categories.id from ads.id.
I have tried this
SELECT categories.id, ads.id
FROM ads
INNER JOIN adcat ON ads.id = adcat.adid
INNER JOIN categories ON categories.id = adcat.catid
But it does not come by the exact value.
obs : I don't get any error just not exact value.
any help will be much appreciated.

Seems to be no reason to go in to categories table if adcat.catid = categories.id and that is the only value you need.
SELECT ads.id,adcat.catid
FROM ads
INNER JOIN adcat
ON ads.id=adcat.adid
Use $row['catid'] with this query.
If in the future you need more columns from categories then you will need a double join:
SELECT categories.id *AS id*,ads.id *AS ads_id*
FROM ads
INNER JOIN adcat ON ads.id = adcat.adid
INNER JOIN categories ON categories.id = adcat.catid
Use $row['id'] with this query.
See *AS id* and *AS ads_id* - remove the stars and you are giving the columns an ALIAS which is basically like a nickname, this can be handy in many cases but especially important in this case since the two columns both have the same names. So now you can call $row['id'] and get categories.id

I'm not sure what exactly is the question but I think you are trying to get not all but single row based on one ads.id if so:
SELECT categories.id ,ads.id
FROM ads
INNER JOIN adcat ON ads.id = adcat.adid
INNER JOIN categories ON categories.id = adcat.catid
WHERE ads.id = your_id_here

Try this:
SELECT categories.id, ads.id
FROM ads, adscat, categories
WHERE ads.id=adcat.adid
AND categories.id = adcat.catid

Related

Mysql: How to get values from other table base from an id

Assuming that I have 3 tables on my database
Table:Category
category_id
Table:container
container_id
category_id
Table:products
container_id
product_id
How do you get all product_id based on a category_id?
For example I have these data inside my tables from above:
Table: category
sour
sweet
Bitter
Table: container
bottled
sachet
Table: product
sugar
vinegar
cocoa
How do you get all Product(tb_product) where category(tb_category) is sweet
You can use INNER JOIN to solve your problem.
SELECT a.*
FROM products a
INNER JOIN container b
on a.container_id = b.container_ID
INNER JOIN Category c
ON b.category_ID = c.categoryID
WHERE c.categoryName = 'sweete'
As you can see, I assume that the Category table has columns category_ID and categoryName. So in my example above,I've use category name to search for all products that belong on certain category.
select p.*
from Category c
join container c2 on c2.category_id = c.category_id
join product p on p.container_id = c2.container_id
where c.name = 'sweet';
Note the order of the tables in the query (which should perform faster than the other answer!)
you can use inner join like this:
SELECT a.product_id FROM products AS a INNER JOIN container AS b on a.container_id = b.container_Id INNER JOIN Category AS c on b.category_Id = c.category_id where c.category_id = 'new'

SQL join and MySQL

In my database I have these tables
products
-------------
id | title |
-------------
1 Cheese
2 Milk
3 Water
etc .....
products_to_city
-----------------------
city_id | product_id |
-----------------------
1 1
1 2
2 3
3 1
3 1
I am using this sql query to fetch the result
SELECT
p.id,
p.title
FROM products p
LEFT JOIN products_to_city ptc ON ptc.id = 1
The problem is that the query above fetches all data from table instead of only where city is 1
What am I doing wrong ?
You didn't tell the query what to join products and products_to_city on. Especially with the LEFT JOIN which will force a result set to include every record in products for every record in products_to_city. I think you want this:
SELECT p.id, p.title
FROM products p
INNER JOIN products_to_city ptc
ON p.id = ptc.product_id
WHERE
ptc.city_id = 1
use this:
SELECT
p.id,
p.title
FROM products p
INNER JOIN products_to_city ptc ON ptc.id = p.id
where ptc.id = 1
You aren't joining products to city, you are getting a match of all the products and city.
SELECT
p.id,
p.title
FROM products p
LEFT JOIN products_to_city ptc ON ptc.product_id = p.id
where ptc.city_id = 1
You're doing an outer join, so where no match is made, you get the row returned anyway. Consider an inner join.
Replace LEFT JOIN with JOIN
That's because LEFT JOIN took even the rows (at the left of the join) that haven't a corrisponing key into the right table.
The JOIN tooks only the colum from "left" and "right" tables that satisfies the pk and fk match
So this will be your solution
SELECT
p.id,
p.title
FROM products p
JOIN products_to_city ptc ON ptc.id = 1
see Basic Question : LEFT OUTER JOIN vs Left Join, (http://stackoverflow.com/questions/2809594/basic-question-left-outer-join-vs-left-join)
they are the same.
you want left inner join.
LEFT JOIN products_to_city ptc ON p.id = ptc.id
When you do this
LEFT JOIN products_to_city ptc
you're telling MySQL (all SQL dbms, actually) to return all the rows from products, even if they don't match the join condition.
To return only those rows that match the join condition, use
INNER JOIN products_to_city ptc ON ptc.product_id = p.id AND (something else)
Note that you need to join the tables using the right column names.
I'm not sure what you want in that "something else" clause, because something like you wrote--pct.id = 1--is normally something you might express in a WHERE clause. The problem is that the products_to_city table doesn't have any column named "id".

MySQL subquery error on multiple tables

I have 3 tables posts, terms and relationships.
posts table:
ID title
1 abc
2 cdf
terms table:
term_id slug
1 jeans
2 shirts
relationships table:
object_id taxonomy_id
1 1
2 1
The MySQL query I used to try to list the titles which have "jeans" related to them
SELECT posts.title
FROM posts, terms, relationships
WHERE (SELECT terms.term_id FROM terms WHERE terms.slug LIKE '%jeans%')
AND (SELECT relationships.object_id FROM relationships WHERE terms.term_id = relationships.taxonomy_id)
AND (posts.ID = relationships.object_id)
It gives me error #1242 - Subquery returns more than 1 row. How can I fix this?
Try this:
SELECT posts.title
FROM posts INNER JOIN relationships ON (posts.ID = relationships.object_id)
INNER JOIN terms ON (terms.term_id = relationships.taxonomy_id)
WHERE terms.slug LIKE '%jeans%';
I don't have your tables, so I can't test, but I think this should work.
Try something like this:
SELECT p.title
FROM posts p
JOIN relationships r
ON r.object_id = p.ID
JOIN terms t
ON t.term_id = r.taxonomy_id
WHERE t.slug LIKE '%jeans%'
SELECT posts.title
FROM posts
INNER JOIN relationships ON (posts.ID = relationships.object_id)
INNER JOIN terms ON (terms.term_id = relationships.taxonomy_id)
WHERE
(terms.slug LIKE '%jeans%')
AND
(terms.term_id = relationships.taxonomy_id)
AND
(posts.ID = relationships.object_id)

Count query stops working correctly after I add a where clause

I have 3 tables: problems, categories, and a joining table for problem_categories
I am trying to get and count all the categories associated with a problem, and count how many problems are associated with each problem.
Here is my query which doesn't return correct results:
SELECT
category_name ,
categories.category_id ,
problems.problem_id,
COUNT(problems.problem_id) as num_problems
FROM
problem_categories
left JOIN
categories
on
problem_categories.category_id = categories.category_id
left join
problems
on
problem_categories.problem_id = problems.problem_id
WHERE
problem_categories.problem_id = 266
GROUP BY
problems.problem_id , category_name
but as soon as I take out the where clause, it returns all the categories and correct counts of problems. But the trick is that I need to query this for a particular problem_id
Any way to adjust this query to get it right? What am I doing incorrectly here?
Thanks!!
Your question is somewhat unclear. How can you count problems if you are selecting a specific one? If you want to count categories associated with a particular problem you do this (I am assuming you have foreign keys and no duplicates in the problem_categories table):
SELECT problem_id, COUNT(category_id) as num_categories
FROM problem_categories
WHERE problem_id = 266
GROUP BY problem_id
then join to problem table if you need to print out more problem information (for efficiency, always get the detail last). If you are wanting to count problem -> category -> problem then do:
select p1.problem_id, (COUNT(DISTINCT(p2.problem_id)) - 1) as num_problems
FROM
(select problem_id, category_id FROM problem_categories where problem_id = 266) as p1
inner join
(select problem_id, category_id FROM problem_categories) as p2
ON p1.category_id = p2.category_id
GROUP by p1.problem_id
Again if you want to show the problem details, join to the problem table to get them. If you want the num_problems and num_categories together join the first query to the second one before joining to the problem table to get the problem detail. i.e.:
SELECT p1.problem_id, p1.num_categories, p2.num_problems
FROM
(SELECT problem_id, COUNT(category_id) as num_categories
FROM problem_categories
WHERE problem_id = 266
GROUP BY problem_id) as p1
INNER JOIN
(SELECT p1.problem_id, (COUNT(DISTINCT(p2.problem_id)) - 1) as num_problems
FROM
(SELECT problem_id, category_id FROM problem_categories where problem_id = 266) as p1
INNER JOIN
(SELECT problem_id, category_id FROM problem_categories) as p2
ON p1.category_id = p2.category_id
GROUP by p1.problem_id) as p2
ON p1.problem_id = p2.problem_id
I think the following should work:
SELECT category_name , categories.category_id, COUNT(*) as num_problems
FROM problem_categories src JOIN CATEGORIES ON src.category_id = categories.category_id
JOIN problem_categories dest ON categories.category_id = dest.category_id
WHERE problems.problem_id = 266
GROUP BY categories.category_id
What you are doing is for the problem id you want you look up the categories ids and from there the names, and from categories id you look how many (if any) problems each has.
The non usage of the problem table is intentional. Also, for this to perform you need to index the problem_categories in BOTH orders.
UPDATE: The Left join can be an inner join, because each category related to problem 266 has at least one problem (problem 266).
you can prepare the categories and the count of problems in them. after that you can use it as part of any query to supply info.
SELECT categories.category_name ,
categories.category_id,
(select COUNT(*)
from problem_categories
where problem_categories.category_id =categories.category_id
) as num_problems
FROM categories
that can be used in a join (and if you wish stored in a temporary table) to supplement info about the categories:
select problem_categories.problem_id,
temp_tab.category_name ,
temp_tab.category_id,
temp_tab.num_problems
from problem_categories,
(
SELECT categories.category_name ,
categories.category_id,
(select COUNT(*)
from problem_categories
where problem_categories.category_id =categories.category_id
) as num_problems
FROM categories
) temp_tab
where problem_categories.problem_id =266
and problem_categories.category_id = temp_tab.category_id
if you will use this with more than one id or without the id condition, it is better to store the info from the category in a temporary table and join it in order not to repeat the calculations.
SELECT p1.problem_id, problem_categories.category_id , category_name ,
COUNT(*) as num_problems
FROM problems p1
LEFT JOIN problem_categories on
p1.problem_id = problem_categories.problem_id
LEFT JOIN categories on
problem_categories.category_id = categories.category_id
LEFT JOIN problems p2 ON
p2.problem_id = problem_categories.problem_id
WHERE p1.problem_id = 266
GROUP BY categories.category_id,p2.problem_id
ORDER BY categories.category_id
Thats it

mySQL JOIN wont return results with 0 count

SELECT categories.*, COUNT(categoryID) AS kritCount
FROM categories AS categories
LEFT JOIN krits ON categories.id = categoryID
WHERE (krits.approved = '1')
GROUP BY categories.id
So this works great except that it does not return a category that has a 0 count of krits in the category.
It will if I remove the WHERE statement but I need the WHERE to only select the krits where the field approved = 1
Any time you reference a column from a left joined table in the where clause (other than testing for NULL values), you force that join to behave like an inner join. Instead, move your test out of the where clause and make it part of the join condition.
SELECT categories. * , COUNT(categoryID) AS kritCount
FROM categories AS categories
LEFT JOIN krits
ON categories.id = categoryID
AND krits.approved = '1'
GROUP BY categories.id
Try this:
SELECT categories. * , COUNT(categoryID) AS kritCount FROM categories AS categories
LEFT JOIN krits ON categories.id = categoryID
WHERE (krits.approved = '1' OR krits.approved IS NULL)
GROUP BY categories.id
From reading the query, it looks like you want call Categories, and for each category, you want a count of Krits (approved) for the respective categories, and when there are none, you still want the Category, but show the count of 0...
Try this
select
cat.*,
COALESCE( kc.KritCount, 0 ) as KritCount
from
Categories cat
left join ( select k.CategoryID,
count(*) KritCount
from
Krits k
where
k.approved = '1'
group by
k.CategoryID ) kc
on cat.id = kc.CategoryID