MySQL query for selecting and counting some fields from two tables - mysql

There is MySQL table post:
mysql> desc post;
+---------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------------+------+-----+---------+----------------+
| post_id | int(11) | NO | PRI | NULL | auto_increment |
| post_content | varchar(50000) | NO | | NULL | |
| post_date | datetime | NO | | NULL | |
| post_summary | varchar(1000) | YES | | NULL | |
| post_title | varchar(300) | NO | | NULL | |
| post_visitors | int(11) | NO | | NULL | |
| user_id | int(11) | NO | MUL | NULL | |
| category_id | int(11) | NO | MUL | NULL | |
+---------------+----------------+------+-----+---------+----------------+
Then, there is table comment:
mysql> desc comment;
+-----------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------+--------------+------+-----+---------+----------------+
| comment_id | int(11) | NO | PRI | NULL | auto_increment |
| comment_content | varchar(600) | NO | | NULL | |
| comment_date | datetime | NO | | NULL | |
| comment_title | varchar(300) | NO | | NULL | |
| user_id | int(11) | NO | MUL | NULL | |
| post_id | int(11) | NO | MUL | NULL | |
+-----------------+--------------+------+-----+---------+----------------+
You can see there is foreign key post_id in the table comment that points to table post.
I need to get next resultset: post_id, post_title, post_date, post_summary, number-of-post-comments.
I tried this, but I'm not getting proper result:
SELECT
p.post_id,
p.post_date,
p.post_summary,
p.post_title,
COUNT(c.post_id)
FROM
post p
LEFT JOIN COMMENT c
ON p.post_id = c.post_id
(I don't work with sql often, this should be easy for those familiar with sql)

Try this
SELECT
p.post_id,
p.post_date,
p.post_summary,
p.post_title,
COUNT(c.post_id) AS number_of_post_comments
FROM
post p
LEFT JOIN COMMENT c
ON p.post_id = c.post_id
GROUP BY p.post_id

Related

MySQL right join with count not working properly

I have the following tables:
MOVIES
+-------------+-------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------+-------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | MUL | NULL | |
| title | varchar(40) | NO | | NULL | |
| description | text | NO | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+-------------+-------------+------+-----+---------+----------------+
MOVIE_VOTES
+------------+------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_id | int(11) | YES | MUL | NULL | |
| movie_id | int(11) | YES | MUL | NULL | |
| like | tinyint(1) | YES | | NULL | |
| created_at | datetime | YES | | NULL | |
| updated_at | datetime | YES | | NULL | |
+------------+------------+------+-----+---------+----------------+
And I want to query all the movies sorted by the number of likes they have. I have this query:
SELECT *, COUNT(*) AS count_likes
FROM movie_votes
RIGHT JOIN movies
ON movies.id=movie_votes.movie_id
WHERE movie_votes.like = 1
GROUP BY movie_id
ORDER BY count_likes;
And this returning the movies sorted by the number of likes BUT not the movies that haven't be voted(liked) yet. For some reason the RIGHT join works as simple join.
I have searched for some relative answers but cant find anything helpful.
You should specify a column name when doing outer joins so that it will count only the non-null values
SELECT movies.id,
movies.user_id,
movies.title,
movies.description,
movies.created_at,
movies.updated_at,
COUNT(movie_votes.movie_id) AS count_likes
FROM movies
LEFT JOIN movie_votes
ON movies.id = movie_votes.movie_id
AND movie_votes.like = 1
GROUP BY movies.id,
movies.user_id,
movies.title,
movies.description,
movies.created_at,
movies.updated_at
ORDER BY count_likes
The condition movie_votes.like = 1 should be put in the ON clause so it will filter the rows in table movie_votes first before joining it to table movies.

MySQL - how can I do a join and order by the sum of votes?

I have schema like this (just experimenting, so if you have improvement suggestions I am all ears):
mysql> describe contest_entries;
+---------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------+----------------+------+-----+---------+----------------+
| entry_id | int(10) | NO | PRI | NULL | auto_increment |
| member_id | int(10) | YES | | NULL | |
| person_name | varchar(10000) | NO | | NULL | |
| date | date | NO | | NULL | |
| platform | varchar(30) | YES | | NULL | |
| business_name | varchar(100) | YES | | NULL | |
| url | varchar(200) | YES | | NULL | |
| business_desc | varchar(3000) | YES | | NULL | |
| guid | varchar(50) | YES | UNI | NULL | |
+---------------+----------------+------+-----+---------+----------------+
9 rows in set (0.00 sec)
mysql> describe contest_votes;
+------------------+---------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------------+---------+------+-----+---------+----------------+
| vote_id | int(10) | NO | PRI | NULL | auto_increment |
| user_id | int(10) | NO | | NULL | |
| contest_entry_id | int(10) | NO | MUL | NULL | |
| vote | int(7) | NO | | NULL | |
+------------------+---------+------+-----+---------+----------------+
And I am trying to pull the data as a leaderboard, ordering the results by the most votes. How would I do that? I am able to do the left-join part, but the sum and the ordering part of the query is confusing me.
Thank you!
SELECT entry_id
FROM contest_entries
LEFT OUTER JOIN contest_votes ON entry_id = contest_entry_id
GROUP BY entry_id
ORDER BY SUM(vote) DESC
select e.entry_id, sum(v.vote) as votes
from contest_entries e
left join contest_votes v on e.entry_id = v.contest_entry_id
group by e.member_id
order by votes desc

MySQL foreign key query returning empty

I have three tables
Let's a demo_organization ;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| org_name | varchar(100) | NO | | NULL | |
| org_type | varchar(100) | NO | | NULL | |
| abn_acn_no | varchar(100) | NO | | NULL | |
| org_url | varchar(120) | NO | | NULL | |
| notes | longtext | NO | | NULL | |
| city | varchar(100) | YES | | NULL | |
Second one is demo_user
mysql> desc demo_user ;
+--------------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+----------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| user_name | varchar(100) | NO | | NULL | |
| first_name | varchar(100) | NO | | NULL | |
| middle_name | varchar(100) | NO | | NULL | |
| last_name | varchar(100) | NO | | NULL | |
| image | varchar(10000) | YES | | NULL | |
| password | varchar(80) | NO | | NULL | |
| role | varchar(20) | NO | | NULL | |
| org_name_id | int(11) | NO | MUL | NULL | |
| timezone_id | int(11) | NO | MUL | NULL | |
And third one is the demo_meeting;look like
mysql> desc demo_meeting ;
+--------------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(200) | NO | | NULL | |
| meetingID | varchar(50) | NO | | NULL | |
| venue_id | int(11) | YES | MUL | NULL | |
| status | int(11) | YES | | NULL | |
| recurring_time | varchar(50) | NO | | NULL | |
| attendee_passwd | varchar(100) | NO | | NULL | |
| moderator_passwd | varchar(100) | NO | | NULL | |
| date_created | datetime | NO | | NULL | |
| start_time | varchar(100) | NO | | NULL | |
| end_time | varchar(100) | NO | | NULL | |
| meeting_duration | varchar(100) | NO | | NULL | |
| meeting_datetime | datetime | YES | | NULL | |
| timezone | varchar(50) | NO | | NULL | |
| reminder | tinyint(1) | NO | | NULL | |
| duration | varchar(20) | NO | | NULL | |
| created_by_id | int(11) | NO | MUL | NULL | |
In third table created_by_id refers to A user of demo_user table(Foreign key)
And org_name_id(demo_user table ) refers to the demo_organization (Foreign key to demo_organization table )
Updated
mysql> desc demo_meetingroom;
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| id | int(11) | NO | PRI | NULL | auto_increment |
| name | varchar(100) | NO | | NULL | |
| type | varchar(200) | NO | | NULL | |
| expired_on | varchar(100) | NO | | NULL | |
| user_id | int(11) | YES | MUL | NULL | |
+------------+--------------+------+-----+---------+----------------+
Now i am trying to get all meetings for a particular organization .
I am writing a query like
select meetingID ,type from demo_meeting as dm ,demo_meetingroom as dmr
Where venue_id IS NOT NULL
and dm.name = dmr.name
AND created_by_id IN
(
SELECT id from demo_user WHERE org_name_id IN
(
SELECT id from demo_organization where id =
(SELECT org_name_id from demo_user WHERE user_name = 'God')
)
);
Unfortunately it is returning me Empty set (But there is value )
Please help me out what might i am doing wrong ?
JOIN the three tables instead of these IN's. Something like:
SELECT
dm.meetingID,
dm.type
FROM demo_meeting dm
INNER JOIN demo_user u ON dm.created_by_id = u.id
INNER JOIN demo_organization org ON u.org_name_id = org.id
WHERE u.user_name = 'God'
AND dm.venue_id IS NOT NULL
Much better if you can use JOIN.
SELECT a.meetingID, d.type
FROM demo_meeting a
LEFT JOIN demo_user b
ON a.created_by_id = b.id
LEFT JOIN demo_organization c
ON b.org_name_id = c.id
LEFT JOIN demo_meetingroom d
ON a.name = d.name
WHERE a.venue_id IS NOT NULL AND
b.username = 'GOD'

MySQL - can't get a left outer join with a count(*) to return the items where count = 0

I have this schema:
mysql> describe suggested_solution_comments;
+-----------------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+----------------+------+-----+---------+----------------+
| comment_id | int(10) | NO | PRI | NULL | auto_increment |
| problem_id | int(10) | NO | | NULL | |
| suggested_solution_id | int(10) | NO | | NULL | |
| commenter_id | int(10) | NO | | NULL | |
| comment | varchar(10000) | YES | | NULL | |
| solution_part | int(3) | NO | | NULL | |
| date | date | NO | | NULL | |
| guid | varchar(50) | YES | UNI | NULL | |
+-----------------------+----------------+------+-----+---------+----------------+
8 rows in set (0.00 sec)
mysql> describe solution_sections;
+---------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------------+------+-----+---------+----------------+
| solution_section_id | int(10) | NO | PRI | NULL | auto_increment |
| display_order | int(10) | NO | | NULL | |
| section_name | varchar(1000) | YES | | NULL | |
+---------------------+---------------+------+-----+---------+----------------+
My query is this:
select s.display_order,
s.section_name,
s.solution_section_id ,
count(c.comment_id) AS comment_count
FROM solution_sections s left outer join suggested_solution_comments c
ON (c.solution_part = s.solution_section_id)
where problem_id = 400
group by s.display_order, s.section_name, s.solution_section_id
order by display_order;
it returns only rows where there is a count > 0 but if the count is 0 it doesnt return those rows.
Any idea how to make it return all the rows? :)
Thanks!!
This is because the where problem_id = 400 removes rows with no corresponding suggested_solution_comments row. Moving the condition from the where filter to the on clause should address the problem:
select s.display_order, s.section_name, s.solution_section_id ,count(c.comment_id)
AS comment_count
from solution_sections s
left outer join suggested_solution_comments c
ON (c.solution_part = s.solution_section_id) AND problem_id = 400
group by s.display_order, s.section_name, s.solution_section_id
order by display_order;

Query randomly returning all items or just some items

I have 4 tables:
mysql> describe solution_sections;
+---------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+---------------------+---------------+------+-----+---------+----------------+
| solution_section_id | int(10) | NO | PRI | NULL | auto_increment |
| display_order | int(10) | NO | | NULL | |
| section_name | varchar(1000) | YES | | NULL | |
+---------------------+---------------+------+-----+---------+----------------+
3 rows in set (0.00 sec)
mysql> describe suggested_solution_comments;
+-----------------------+----------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-----------------------+----------------+------+-----+---------+----------------+
| comment_id | int(10) | NO | PRI | NULL | auto_increment |
| problem_id | int(10) | NO | | NULL | |
| suggested_solution_id | int(10) | NO | | NULL | |
| commenter_id | int(10) | NO | | NULL | |
| comment | varchar(10000) | YES | | NULL | |
| solution_part | int(3) | NO | | NULL | |
| date | date | NO | | NULL | |
+-----------------------+----------------+------+-----+---------+----------------+
mysql> describe users;
+--------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+--------------+---------------+------+-----+---------+----------------+
| user_id | int(10) | NO | PRI | NULL | auto_increment |
| first_name | varchar(100) | NO | | NULL | |
| last_name | varchar(100) | NO | | NULL | |
| email | varchar(150) | NO | | NULL | |
| user_pass | varchar(40) | NO | | NULL | |
| zip | varchar(100) | NO | | NULL | |
| country | varchar(100) | NO | | NULL | |
| city | varchar(100) | NO | | NULL | |
| state | varchar(100) | NO | | NULL | |
| lat | float(9,6) | YES | | NULL | |
| lng | float(9,6) | YES | | NULL | |
| agreed_terms | tinyint(1) | YES | | NULL | |
| join_date | date | NO | | NULL | |
| last_login | date | NO | | NULL | |
| bio_blurb | varchar(5000) | YES | | NULL | |
+--------------+---------------+------+-----+---------+----------------+
15 rows in set (0.03 sec)
mysql> describe member_photo;
+-------------------+---------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+-------------------+---------------+------+-----+---------+----------------+
| photo_id | int(10) | NO | PRI | NULL | auto_increment |
| member_id | int(10) | NO | | NULL | |
| photo_description | varchar(3000) | YES | | NULL | |
| photo_path | varchar(1000) | NO | | NULL | |
| small_thumb | varchar(1000) | YES | | NULL | |
| mid_thumb | varchar(1000) | YES | | NULL | |
| is_main_photo | tinyint(1) | YES | | NULL | |
+-------------------+---------------+------+-----+---------+----------------+
And I have a query like this:
select comment_id,
commenter_id,
section_name,
comment,
solution_part,
display_order,
solution_section_id,
suggested_solution_id,
DAYOFMONTH(date),
DAYNAME(date),
YEAR(date),
MONTH(date),
first_name,
last_name,
email,
small_thumb,
mid_thumb
from solution_sections
left join suggested_solution_comments on
solution_sections.solution_section_id = suggested_solution_comments.solution_part
left join users on
suggested_solution_comments.commenter_id = users.user_id
left join member_photo on
suggested_solution_comments.commenter_id = member_photo.member_id
where suggested_solution_id = 61 OR
suggested_solution_id IS NULL
order by solution_section_id,
comment_id,
section_name,
comment,
solution_part,
display_order;
What its supposed to do is get each section_name from the solution_sections table, and then find the comments (and data about who commented). Sometimes there are no comments, but it should still return at least the row with section_name and all other things being null.
But for some reason it does not. And the weirdest part is that if I give it a different suggested_solution_id to match, it will return all of the rows of solution_sections.
Any ideas why such a thing might happen? Thank you!!
And I just realized one thing - if another comment has been made for any problem_id, this query won't return the row with that section.
You need a left outer join to view all records from your parent table when child records are not guaranteed to exits. I'd also avoid adding a where clause when using outer joins.. I think its more readable to keep your join in a subselect, and filter the results.. Try something like this:
select * from
(
select sc.comment_id,
sc.commenter_id,
ss.section_name,
sc.comment,
sc.solution_part,
ss.display_order,
ss.solution_section_id,
sc.suggested_solution_id,
DAYOFMONTH(sc.date),
DAYNAME(sc.date),
YEAR(sc.date),
MONTH(sc.date),
u.first_name,
u.last_name,
u.email,
mp.small_thumb,
mp.mid_thumb
from solution_sections ss
left outer join suggested_solution_comments sc on ss.solution_section_id = sc.solution_part
left outer join users u on sc.commenter_id = u.user_id
left outer join member_photo mp on sc.commenter_id = mp.member_id) a
where a.suggested_solution_id = 61 OR
a.suggested_solution_id IS NULL
order by a.solution_section_id,
a.comment_id,
a.section_name,
a.comment,
a.solution_part,
a.display_order;
EDIT:
select sc.comment_id,
sc.commenter_id,
ss.section_name,
sc.comment,
sc.solution_part,
ss.display_order,
ss.solution_section_id,
sc.suggested_solution_id,
DAYOFMONTH(sc.date),
DAYNAME(sc.date),
YEAR(sc.date),
MONTH(sc.date),
u.first_name,
u.last_name,
u.email,
mp.small_thumb,
mp.mid_thumb
from solution_sections ss
left outer join suggested_solution_comments sc on ss.solution_section_id = sc.solution_part
AND sc.suggested_solution_id = 61
left outer join users u on sc.commenter_id = u.user_id
left outer join member_photo mp on sc.commenter_id = mp.member_id
order by solution_section_id,
comment_id,
section_name,
comment,
solution_part,
display_order;
If you want to show solution_sections even if all the rest doesn't exist, you can use "left outer join":
select comment_id,commenter_id, section_name, comment, solution_part,
display_order, solution_section_id, suggested_solution_id,
DAYOFMONTH(date), DAYNAME(date), YEAR(date), MONTH(date),
first_name, last_name, email, small_thumb,mid_thumb
from solution_sections
left outer join suggested_solution_comments on solution_sections.solution_section_id = suggested_solution_comments.solution_part
and suggested_solution_id = 61
left outer join users on suggested_solution_comments.commenter_id = users.user_id
left outer join member_photo on suggested_solution_comments.commenter_id = member_photo.member_id
where solution_section_id = ????
order by solution_section_id, comment_id, section_name, comment, solution_part,display_order;
ps. try to use aliases for tables it's more readable :-)