Count in mysql database - mysql

This my query:
Select articles.id,articles.userid,articles.article,count(articles_likes.id), count(article_dislikes.id)
from articles
Left join article_likes
on article_likes.id=articles.id
Left join article_dislikes
on article_dislikes.id=articles.id
group by articles.id ;
I want to count the number of rows in article_likes table and article_dislikes table im getting the value correct upto 2 rows..when there is a third and so on entries..I'm getting wrong counting of rows...
I don't know where the problem is ..I think I may be getting wrong values because I'm using the same table for two times...please help me
I have three tables
1)articles contains id,userid and article
2)Articles_likes table contains-like_id ,user_id and article_id
3)Articles_dislikes table contains dislike_id ,user_id and article_id

Aggregate separately in each of the tables articles_likes and articles_dislikes and then join articles to the results:
select a.id, a.userid, a.article,
coalesce(l.likes, 0) likes,
coalesce(d.dislikes, 0) dislikes
from articles a
left join (
select article_id, count(*) likes,
from articles_likes
group by article_id
) l on l.article_id = a.id
left join (
select article_id, count(*) dislikes,
from articles_dislikes
group by article_id
) d on d.article_id = a.id
Also the correct join of articles_likes and articles_dislikes to articles is by the column article_id to the id of articles.

Related

Can you use Count(*) in an inner join?

Currently I have the following database:
Table 1: Customer_Stores
unique_id
page_address
date_added
guide_summary
user_name
cover_photo
guide_title
Table 2: Customer_Stories_Likes
story_id
likex
The 'like' column in the second table contains a 1 or a 0 to indict whether or not a user has liked a post.
What I'd like to do is join these two tables together with 'post_id' and count all of the 'likes' for all the posts based on post_id and order these by how many likes each post got. Is this possible with a single statement? or is it better to use a Count(*) to first determine how many likes each post has?
Yes, it's possible, but you don't need an inner join, because you don't actually need the posts table to do it.
SELECT post_id, count(like) AS post_likes
FROM likes
WHERE like = 1
GROUP BY post_id
ORDER BY post_likes DESC
If you need other information from the posts table as well, you could join it to a subquery that gets the like counts.
SELECT posts.*, like_count
FROM
posts LEFT JOIN
(SELECT post_id, count(like) AS like_count
FROM likes
WHERE like = 1
GROUP BY post_id) AS post_likes
ON posts.post_id = post_likes.post_id
ORDER BY like_count DESC
I used LEFT JOIN rather than INNER JOIN, you can use INNER JOIN if you don't want to include posts with no likes.

Inner Join 2 tables and count occurrences of foreign key in each

I am using Mysql and I have 3 tables,
banners (id,type,page)
clicks (id,banner_id)
impressions (id,banner_id)
Where banner_id is the foreign key in clicks and impressions tables. I need to produce rows like this
Required Result Table
id, type, clicks_count, impressions_count
Perfomance-wise, what is the best mysql query to use to achieve the result above.
Simply JOIN the three tables, use COUNT() and GROUP BY:
select id, type, count(c.id) clicks_count, count(i.id) as impressions_count
from banners b
left join clicks c on b.id = c.banner_id
left join impressions i on b.id = i.banner_id
group by id, type
Or use correlated sub-queries to count:
select id, type,
(select count(*) from clicks c where b.id = c.banner_id) clicks_count,
(select count(*) from impressions i where b.id = i.banner_id) impressions_count
from banners b

Combining count from one table and distinct from another

I've setup a contest where video submissions are sent in and then people vote on them. Submissions are sent into a table submissions with this structure:
submission_id, title, videoname
The voting table votes structure is:
video_id, voter_id
The video_id correlates to the submission_id in the submissions table.
I want to get the number of votes for each video like so:
select video_id, count(1) from votes group by submission_id
But I also want to display the title for each video so the result would be:
video_id, count, title
I am a sql noob so please forgive me if this is a simple statement. I have done some research and was not able to come up with something on my own and would appreciate any help.
I would recommend doing a LEFT JOIN instead of an INNER JOIN... and COUNT(v.video_id) instead of COUNT(*). This way you will still return submissions that currently have 0 votes:
select
s.submission_id as video_id,
count(v.video_id) as vote_count,
s.title
from
submissions s
left join votes v on v.video_id = s.submission_id
group by
s.submission_id,
s.title
select s.submission_id, s.title, s.videoname, c.cnt
from
submissions s,
(select video_id, count(1) as cnt from votes group by video_id) c
where
s.submission_id = c.video_id
This will return every video from you submissions table and show the number of votes in the votes table. If there have not been any votes it will show up in the results with a NULL as the Votes column
SELECT video_id, title, COUNT(voter_id) Votes
FROM submissions s
LEFT OUTER JOIN votes v ON s.submission_id = v.video_id
GROUP BY video_id, title,
You have to make a join for retrieve the votes and the video title, between the two tables like this :
SELECT submissions.submission_id
, COUNT(1)
, submissions.videoname
FROM submissions LEFT OUTER JOIN votes
ON votes.video_id = submissions.submission_id
GROUP BY submissions.submission_id, submissions.videoname

MYSQL group by and inner join

I have an article table which holds the number of articles views for each day. A new record is created to hold the count for each seperate day for each article.
The query below gets the article id and total views for the top 5 viewed article id for all time :
SELECT article_id,
SUM(article_count) as cnt
FROM article_views
GROUP BY article_id
ORDER BY cnt DESC
LIMIT 5
I also have a seperate article table which holds all the article fields. I want to ammend the query above to join to the article table and get two fields for each article id. I have tried to do this below but count is comming back incorrectly :
SELECT article_views.article_id, SUM( article_views.article_count ) AS cnt, articles.article_title, articles.artcile_url
FROM article_views
INNER JOIN articles ON articles.article_id = article_views.article_id
GROUP BY article_views.article_id
ORDER BY cnt DESC
LIMIT 5
Im not sure exactly what im doing wrong. Do I need to do a subquery?
Add articles.article_title, articles.artcile_url to the GROUP BY clause:
SELECT
article_views.article_id,
articles.article_title,
articles.artcile_url,
SUM( article_views.article_count ) AS cnt
FROM article_views
INNER JOIN articles ON articles.article_id = article_views.article_id
GROUP BY article_views.article_id,
articles.article_title,
articles.artcile_url
ORDER BY cnt DESC
LIMIT 5;
The reason you were not getting correct result set, is that when you select rows that are not included in the GROUP BY nor in an aggregate function in the SELECT clause MySQL picks up random value.
You are using a MySQL (mis) feature called Hidden Columns, because article title is not in the group by. However, this may or may not be causing your problem.
If the counts are wrong, then I think you have duplicate article_id in the article table. You can check this by doing:
select article_id, count(*) as cnt
from articles
group by article_id
having cnt > 1
If any appear, then that is your problem. If they all have different titles, then grouping by the title (as suggested by Mahmoud) would fix the problem.
If not, one way to fix it is the following:
SELECT article_views.article_id, SUM( article_views.article_count ) AS cnt, articles.article_title, articles.artcile_url
FROM article_views INNER JOIN
(select a.* from articles group by article_id) articles
ON articles.article_id = article_views.article_id
GROUP BY article_views.article_id
ORDER BY cnt DESC
LIMIT 5
This chooses an abitrary title for the article.
Your query looks basically right to me...
But the value returned for cnt is going to be dependent upon article_id column being UNIQUE in the articles table. We'd assume that it's the primary key, and absent a schema definition, that's only an assumption.)
Also, we're likely to assume there's a foreign key between the tables, that is, there are no values of article_id in the articles_view table which don't match a value of article_id on a row from the articles table.
To check for "orphan" article_id values, run a query like:
SELECT v.article_id
FROM articles_view v
LEFT
JOIN articles a
ON a.article_id = v.article_id
WHERE a.article_id IS NULL
To check for "duplicate" article_id values in articles, run a query like:
SELECT a.article_id
FROM articles a
GROUP BY a.article_id
HAVING COUNT(1) > 1
If either of those queries returns rows, that could be an explanation for the behavior you observe.

Count multiple tables

I have several mysql tables like this:
blogs
entry_id
member_d
articles
entry_id
member_d
posts
entry_id
member_d
I want to count the total entries by a specific member. I currently have this (while only using 3 tables for this example, there is in fact about 10 - 20 tables all structured the same):
SELECT COUNT('member_id') FROM blogs WHERE member_id=3 LIMIT 1;
SELECT COUNT('member_id') FROM articles WHERE member_id=3 LIMIT 1;
SELECT COUNT('member_id') FROM posts WHERE member_id=3 LIMIT 1;
You see the repetition? Is there any way of condensing that down to 1 query for example (doubt this works):
SELECT COUNT(blogs.'member_id') as total_blogs,
COUNT(articles.'member_id') as total_articles,
COUNT(posts.'member_id') as total_posts
FROM blogs,articles,posts WHERE member_id=3 LIMIT 1;
P.S. Tried searching stackoverflow and google but keep getting things about using COUNT(*) or using groups, etc...
This Works,
SELECT
(SELECT COUNT('member_id') FROM blogs WHERE member_id=3) as total_blogs,
(SELECT COUNT('member_id') FROM articles WHERE member_id=3) as total_articles,
(SELECT COUNT('member_id') FROM posts WHERE member_id=3) as total_posts
and gives you all info in only one record
SELECT COUNT(*) FROM(
SELECT member_id FROM blogs
UNION ALL
SELECT member_id FROM articles
UNION ALL
SELECT member_id FROM posts
) AS activity
WHERE member_id=3
GROUP BY member_id
Sqlfiddle demonstration: http://sqlfiddle.com/#!2/366bd/2
Just for the record, I add here a second solution that admit multiple selection of IDs in a single query
SELECT m.member_id,
COALESCE(blogs.total_blogs,0) as total_blogs,
COALESCE(articles.total_articles,0) as total_articles,
COALESCE(posts.total_posts,0) as total_posts
FROM members m -- I guess this table exists
LEFT JOIN (SELECT member_id, COUNT('member_id') as total_blogs FROM blogs GROUP BY member_id) as blogs on m.member_id = blogs.member_id
LEFT JOIN (SELECT member_id, COUNT('member_id') as total_articles FROM articles GROUP BY member_id) as articles on m.member_id = articles.member_id
LEFT JOIN (SELECT member_id, COUNT('member_id') as total_posts FROM posts GROUP BY member_id) as posts on m.member_id = posts.member_id
where m.member_id in (3,4,5)
fiddle here