I have three tables:
person_table
id| name | gender
1 | Joe | male
2 | Jane |female
3 | Janet | female
4| Jay | male
etc...
product_table
id| name
1 | magazine
2 | book
3 |paper
4 | novel
etc...
**person_product
person_id| product_id | quantity
1 | 1 | 1
1 | 3 | 3
2 | 3 | 1
4 | 4 | 2
etc...
I have tried to make a query that will return a table like this:
person_id| person_name | product_name| quantity
but i can't make it so that if lets say John has no books, it should display
(johns id) John|book|0
instead of just skipping this line.
Where did i go wrong?
here is what i managed to come up with:
SELECT p.*, f.name, l.quantity
FROM person_product AS l
INNER JOIN people_table AS p ON l.person_id=p.id
INNER JOIN product_table AS f ON l.product_id=f.id
ORDER BY id`
It seems that you're generating a report of all people, against all products with the relevant quantity; on a large data set this could take a while as you're not specifically joining product to person for anything other than quantity:
SELECT
p.id,
p.name,
p.gender,
f.name,
IFNULL(l.quantity,0) AS quantity
FROM person_table AS p
JOIN product_table AS f
LEFT JOIN person_product AS l
ON l.person_id = p.id
AND l.product_id = f.id
ORDER BY p.id, f.name
Which results in:
Is that more-or-less what you're after?
you need to start with people_table than using left join you need to bring other table data.
as you need 0 value if null than you can use function IFNULL
SELECT p.*, f.name, IFNULL(l.quantity,0)
FROM people_table AS p
LEFT JOIN person_product AS l ON l.person_id=p.id
LEFT JOIN product_table AS f ON l.product_id=f.id
ORDER BY p.id
if has no book shouldn't appear in the table , try this (easy to understand) :
SELECT NAME
,'0'
,'0'
FROM person_table
WHERE id NOT IN (
SELECT person_id
FROM person_product
)
UNION
SELECT person_id
,product_id
,quantity
FROM person_product;
Related
I have three mysql tables, category,students and student_category. for each student there is 1 or more category will be there and it is stored in student_category as follows.
1) Categgory
----------------------------
id | category_name
---------------------------
1 | A
2 | B
3 | C
4 | D
2) Students
--------------------------
id | name
--------------------------
1 | John
2 | Kumar
3 | Ashok
4 | Jorge
5 | Suku
-------------------------
2) student_category
-----------------------------------------
id | student_id | category_id
-----------------------------------------
1 | 1 | 2
2 | 1 | 4
3 | 2 | 3
4 | 2 | 1
5 | 3 | 2
------------------------------------------
I need to select students which contain category_id 2 and 4.
i used query as follows but it return either students contain category 2 or category 4.
select A.name from students A, student_category B where A.id=B.student_id
and B.category_id IN (2,4)
Try this query:
SELECT t1.id,
t3.name
FROM students t1
INNER JOIN student_category t2
ON t1.id = t2.student_id
INNER JOIN students t3
ON t1.id = t3.id
WHERE t2.category_id IN (2, 4)
GROUP BY t1.id
HAVING COUNT(DISTINCT t2.category_id) = 2
Explanation:
This query joins together the students and student_category tables, and then removes all records which are not category 2 or 4. This means that each student would then only have category 2 and 4 records associated with him. The HAVING clause then restricts further by requiring that a student have two distinct categories, which if true must mean that the student has both category 2 and 4.
Demo here:
SQLFiddle
try this :
select name from Students where id in (select student_id from student_category where category_id in (2,4))
your query is fine btw.
Try this one:
select
s.name
from
Students s,
Categgory c,
student_category sc
where
sc.student_id = s.id
and sc.category_id = c.id
and c.id = 2
and c.id = 4
You can check it on SQL Fiddle.
Have to take distinct student name as it will repeat if a student falls in more than one category.
I have this tables :
Table: Articles
id | title | display |
-----------------------------------
1 | Fkekc | 1 |
2 | ldsdf | 1 |
3 | OTRld | 0 |
4 | QCRSA | 1 |
Table: Likes
id | article_id | like | type
----------------------------------------
1 | 1 | 121 | 1
2 | 1 | 652 | 2
3 | 2 | 12 | 1
4 | 1 | 5 | 3
i want get this result:
Article [1] => 778
Article [2] => 12
Article [3] => 0
Article [4] => 0
I use LEFT JOIN between two tables but this return records per likes table. so i get three record of article 1
My code:
SELECT articles.*,likes.like FROM `articles` LEFT JOIN `likes` ON articles.id=likes.article_id WHERE display='1'
I know that i must use SUM() but i didn't know how use it
With your answers i find that i must use this:
SELECT articles.*, sum(likes.like) as likesSum FROM `articles` LEFT JOIN `likes`ON articles.id=likes.article_id WHERE display='1' GROUP BY articles.id
But i want to set filter in query. so use this :
SELECT articles.*, sum(likes.like) as likesSum FROM `articles` LEFT JOIN `likes`ON articles.id=likes.article_id WHERE display='1' && likesSum>='100' GROUP BY articles.id
But above code doesn't return any result
This is your query
SELECT articles.*,COALESCE(sum(likes.like),0) as total_like FROM
`articles` LEFT JOIN `likes` ON articles.id=likes.article_id group by
articles.id
Output is
SELECT articles.*, sum(likes.like) as likesSum FROM `articles` LEFT JOIN `likes`ON articles.id=likes.article_id WHERE display='1' GROUP BY articles.id
This should work for you perfectly..
SELECT articles.id, sum(likes.like) from articles left join likes on (articles.id=likes.article_id) group by articles.id order by articles.id
See the use of SUM() with GROUP BY
This visual representation is great to understand the joins: http://www.codeproject.com/Articles/33052/Visual-Representation-of-SQL-Joins
You did everything right but only one this missing. You should have used group by
SELECT articles.*, likes.like
FROM `articles`
LEFT JOIN `likes` ON articles.id = likes.article_id
WHERE display = '1'
GROUP BY likes.article_id
First, apologies if the title doesn't match the question. Well, the problem is how to build this query...
I have a table called category It contains categories of my stuff(movies). It's like this...
--------------------------------
ID | name | parent_category
--------------------------------
1 | love | 0
2 | action | 0
3 | fear | 0
4 | passion| 1
5 | danger | 2
6 | death | 3
--------------------------------
So, as you see, each category has a parent category. Except the first 3. They're parents.
And movies table is like this...
--------------------------------
ID | name | category
--------------------------------
1 | aaaa | 1
2 | bbbbbb | 2
3 | cccc | 2
4 | ddddddd| 1
5 | eeeeee | 3
6 | fffff | 3
--------------------------------
So, what i want to do is, to select movies by parent category. Which means if I click category, love, it should select all the movies of categories that having love as the parent category.
So, how to write this in a single query ?
If the parents are only one level deep, then you can use joins:
select m.*,
coalesce(cp.id, c.id) as parent_id,
coalesce(cp.name, c.name) as parent_name
from movies m left join
categories c
on m.category = c.id left join
categories cp
on c.parent_category = cp.id;
Actually, if you only want the id, you don't need two joins:
select m.*,
(case when c.parent_id > 0 then c.parent_id else c.id end) as parent_id
from movies m left join
categories c
on m.category = c.id ;
Or, more simply:
select m.*, greatest(c.parent_id, c.id) as parent_id
. . .
to select rows filtered by condition on secend table use join in FROM clause or subquery in condition with IN or EXISTS function. To compare field with some string you can use LIKE operator.
If you are filtering based on parent_category -
SELECT b.*, a.name FROM movies b
LEFT JOIN categories a ON a.id = b.category
WHERE a.parent_category = 1;
I'm having difficulty figuring out how to create the proper syntax for my query.
Here is what i'm pulling. I have 2 tables.
Table 1 : Fields (user_id, name)
Table 2 : Fields (user_id, type, are_code, phone_number).
Table 1 can only have 1 record per user_id.
1 | John Doe
Table 2 can have up to 3 records per user_id:
1 | Home | 123 | 456.4567
1 | Work | 000 | 987.1467
1 | Mobi | 098 | 987.1756
How can i select everything so that my table will result in 1 record pulled like so :
user_id | name | home# | work# | mobi#
I tried this, which duplicates and doubles rows based on amount of entries within Table 2.
SELECT a.user_id,
b.area_code, b.phone_number
FROM users a
INNER JOIN user_contact_phones b ON a.user_id = b.user_id
That unfortunately returned 3 rows which is not good :(.
1 | John Doe | area | home# |
1 | John Doe | area | work# |
1 | John Doe | area | mobi# |
Any help and or pointers would be greatly appreciated.
Try this out:
SELECT
u.user_id,
u.name,
MAX(CASE WHEN p.type = 'Home' THEN phone_number END) HomeNumber,
MAX(CASE WHEN p.type = 'Work' THEN phone_number END) WorkNumber,
MAX(CASE WHEN p.type = 'Mobi' THEN phone_number END) MobiNumber
FROM phones p
JOIN users u ON p.user_id = u.user_id
GROUP BY u.user_id, u.name
Output:
| USER_ID | NAME | HOMENUMBER | WORKNUMBER | MOBINUMBER |
|---------|----------|------------|------------|------------|
| 1 | John Doe | 456.4567 | 987.1467 | 987.1756 |
Fiddle here.
Also note that you can remove u.name if u.user_id determines u.name... which is most likely the case as it seems to be a primary key. That would speed things up a little bit.
Note: This assumes that you cant have more than one same type for the same user (as it is in your example data, which only has one column for home, work and mobile.
Use user_contact_phones.type to get exact what you want, like-
SELECT a.user_id,
b.area_code, b.phone_number
FROM users a
INNER JOIN user_contact_phones b ON a.user_id = b.user_id where b.type='Home'
Here's a solution that will work:
select u.user_id, u.name,
thome.area_code as home_area_code, thome.phone_number as home_phone_number,
twork.area_code as work_area_code, twork.phone_number as work_phone_number,
tmobi.area_code as mobi_area_code, tmobi.phone_number as mobi_phone_number
from table1 u
left outer join table2 thome on u.user_id = thome.user_id and thome.type = 'Home'
left outer join table2 twork on u.user_id = twork.user_id and twork.type = 'Work'
left outer join table2 tmobi on u.user_id = tmobi.user_id and tmobi.type = 'Mobi'
Please note the use of left outer join instead of inner join in case the record for a particular type does not exist. You will get null values for those columns in your result set with left outer join. With inner join, you would not get a result for a user that did not have all three types. Good luck!
I need to generate some big data from many tables, regarding filters, at there also i need to get the sum of some columns, and also counts of rows like example
i have 5 records
ID | NAME | DELETED
1 | A | 1
2 | A | 0
3 | A | 1
4 | B | 1
5 | C | 1
I have the query,
SELECT p.name, sum(p.deleted) as del, count(p.id) as numbers from products as p
join other AS b ON p.id=b.id
The output i need is,
The sum of deleted records
NAME | Deletion | Count
A | 2 | 3
B | 1 | 1
C | 1 | 1
Try this ::
SELECT
p.name,
sum(p.deleted) as del,
count(id) as numbers
from products as p
join other AS b ON p.id=b.id
group by p.name
You should not need to join to get your result. This should work:
SELECT name, sum(deleted), count(1)
FROM products
GROUP BY name
SELECT name,
SUM(CASE WHEN deleted = 1 THEN 1 ELSE 0 END) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name
OR
SELECT name,
SUM(deleted) Deletion,
COUNT(*) `COunt`
FROM products
GROUP BY name;
SQLFiddle Demo (both queries)