sql with one count() another count() in LEFT JOIN - mysql

having:
SELECT *, COUNT(MakeModel) as `count`
FROM (`table_a`)
GROUP BY `MakeModel`
ORDER BY `count` DESC
Works fine for me (count = 2)
extend this query with a LEFT JOIN like this:
SELECT *, COUNT(distinct b.rating) as ratings
FROM (`table_a`)
LEFT JOIN `model_ratings` AS b ON `b`.`MakeModel` = `table_a`.`MakeModel`
GROUP BY `table_a`.`MakeModel`
Also works fine (ratings = 3),
but combine the 2 counts like this:
SELECT *, COUNT(table_a.MakeModel) as `count`, COUNT(distinct b.rating) as ratings
FROM (`table_a`)
LEFT JOIN `model_ratings` AS b ON `b`.`MakeModel` = `table_a`.`MakeModel`
GROUP BY `table_a`.`MakeModel`
ORDER BY `count` DESC
then (count= 6 ) and (ratings = 3).
So count becomes ('count' times 'ratings').
But I need (count= 2 ) and (ratings = 3)
What am I missing here?

Found out by myself
COUNT() and GROUP inside the LEFT JOIN first
SELECT *, COUNT(table_a.MakeModel) as `count`, b.rating as ratings
FROM (`table_a`)
LEFT JOIN (
SELECT MakeModel, COUNT(distinct rating)
FROM `model_ratings`
GROUP BY MakeModel
) AS b ON `b`.`MakeModel` = `table_a`.`MakeModel`
GROUP BY `table_a`.`MakeModel`
ORDER BY `count` DESC

Related

Sum of grouped COUNT IN MySQL

I wrote this query
SELECT
country,
COUNT(DISTINCT tmp_tbl.user_guid) AS number_of_customers
FROM complete_tests c INNER JOIN
( SELECT DISTINCT d.dog_guid,
u.user_guid,
u.country
FROM dogs d INNER JOIN users u ON d.user_guid = u.user_guid
WHERE (u.exclude = 0 OR u.exclude IS NULL)
AND (d.exclude = 0 OR d.exclude IS NULL)
)
AS tmp_tbl ON c.dog_guid = tmp_tbl.dog_guid
GROUP BY country
ORDER BY number_of_customers DESC
And I need to add another variable that calculates the percentage of total
when I add
number_of_customers/SUM(number_of_customers)
or SUM(COUNT(DISTINCT tmp_tbl.user_guid)) / COUNT(DISTINCT tmp_tbl.user_guid)
it gives me error
Analytic functions come in handy here. Assuming you are using MySQL 8+:
SELECT country,
COUNT(DISTINCT tmp_tbl.user_guid) AS number_of_customers,
100.0 * COUNT(DISTINCT tmp_tbl.user_guid) /
SUM(COUNT(DISTINCT tmp_tbl.user_guid)) OVER () AS pct_customers
FROM complete_tests c
INNER JOIN
(
SELECT DISTINCT d.dog_guid, u.user_guid, u.country
FROM dogs d
INNER JOIN users u ON d.user_guid = u.user_guid
WHERE (u.exclude = 0 OR u.exclude IS NULL) AND
(d.exclude = 0 OR d.exclude IS NULL)
) AS tmp_tbl
ON c.dog_guid = tmp_tbl.dog_guid
GROUP BY
country
ORDER BY
number_of_customers DESC;

Mysql Query to get latest record while using multiple joins, group by and sum()

SELECT Task_Entry_Icode, Task_Master_Icode, Work_Progress,SUM(A.Logged_Hours) as logged,B.*
FROM task_entry A INNER JOIN task_master B on A.Task_Master_Icode=B.Task_Icode
WHERE Task_Entry_Icode IN (
SELECT MAX(Task_Entry_Icode)
FROM task_entry
GROUP BY Task_Master_Icode
);
SELECT *
FROM task_master A INNER JOIN task_entry B ON A.Task_Icode=B.Task_Master_Icode
WHERE Created_On IN (
SELECT MAX(Created_On)
FROM task_entry
GROUP BY Task_Master_Icode
) AND A.Task_Created_By='7';
this works for me but if i use sum() it returns only one record
SELECT
B.Task_Entry_Icode,
B.Task_Master_Icode,
(SELECT Work_Progress FROM task_entry WHERE Task_Master_Icode=B.Task_Master_Icode ORDER BY B.Created_On DESC LIMIT 1 OFFSET 0),
SUM(B.Logged_Hours)
FROM
task_master A INNER JOIN task_entry B ON A.Task_Icode=B.Task_Master_Icode
GROUP BY
B.task_master_icode;

Sub Query counting character strings in MySQL

LEFT JOIN
(
SELECT user_id, review, COUNT(user_id) totalCount
FROM reviews
GROUP BY user_id
) b ON b.user_id= b.user_id
I am trying to fit WHERE LENGTH(review) > 100 in this somewhere but every I put it, it gives me problems.
The sub-query above counts all total reviews by user_id. I simply want to add one more qualification. Only count reviews greater than 100 length.
On a side note, I've seen the function CHAR_LENGTH -- not sure if that i what I need either.
EDIT:
Here is complete query working perfectly as expected for my needs:
static public $top_users = "
SELECT u.username, u.score,
(COALESCE(a.totalCount, 0) * 4) +
(COALESCE(b.totalCount, 0) * 5) +
(COALESCE(c.totalCount, 0) * 1) +
(COALESCE(d.totalCount, 0) * 2) +
(COALESCE(u.friend_points, 0)) AS totalScore
FROM users u
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount
FROM items
GROUP BY user_id
) a ON a.user_id= u.user_id
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount
FROM reviews
GROUP BY user_id
) b ON b.user_id= u.user_id
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount
FROM ratings
GROUP BY user_id
) c ON c.user_id = u.user_id
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount
FROM comments
GROUP BY user_id
) d ON d.user_id = u.user_id
ORDER BY totalScore DESC LIMIT 25;";
LENGTH() returns the length of the string measured in bytes. You probably want CHAR_LENGTH() as it will give you the actual characters.
SELECT user_id, review, COUNT(user_id) totalCount
FROM reviews
WHERE CHAR_LENGTH(review) > 100
GROUP BY user_id, review
You're also not using GROUP BY correctly.
See the documentation
The query that you want is:
LEFT JOIN
(
SELECT user_id, COUNT(user_id) totalCount,
sum(case when length(review) > 100 then 1 else 0 end
) as NumLongReviews
FROM reviews
GROUP BY user_id
) b ON b.user_id= b.user_id
This counts both the reviews and the "long" reviews. That count is done using a case statement nested in a sum() function.

Query for multiple count values

SELECT cm.commenter_id,
cm.comment,
m.id,
(
SELECT COUNT(*) AS r_count
FROM comments
GROUP BY comments.commenter_id
) AS count,
m.display_name
FROM comments cm
INNER JOIN members m
ON cm.commenter_id = m.id
From this query I want to get the display_name for the person with the highest count of comments. Any guidance is appreciated.
SELECT m.id, m.display_name, COUNT(*) totalComments
FROM comments cm
INNER JOIN members m
ON cm.commenter_id = m.id
GROUP BY m.id, m.display_name
HAVING COUNT(*) =
(
SELECT COUNT(*) totalCount
FROM Comments
GROUP BY commenter_id
ORDER BY totalCount DESC
LIMIT 1
)
SQLFiddle Demo
SQLFiddle Demo (with duplicates)
I think the simplest way is just to sort your query and take the first row:
SELECT cm.commenter_id,
cm.comment,
m.id,
(
SELECT COUNT(*) AS r_count
FROM comments
GROUP BY comments.commenter_id
) AS count,
m.display_name
FROM comments cm
INNER JOIN members m
ON cm.commenter_id = m.id
order by count desc
limit 1

SQL Query with Joins Counting multiple Results Per Record Ordering By Count

I have a table called Request.
Other tables are linked to the Request table through a request id.
There is a TwitterTweet table and a FacebookPost table.
So a single request can have 50 TwitterTweets and/or 20 FacebookPosts or any amount of Tweets/Posts
We can add them together for a total count of 70.
I'm trying to create a query that could tell me what is the request with the highest total count.
I know this is wrong:
(I attempted to just order them by the counts within the TwitterTweet, but it would not let me do an OUTER JOIN which I thought
would bring back the Count.count column. It forced me to do a Left Join for it to compile. My Logic was to do a join so
that the results were calculated for each row by the requestid)
SELECT r1.`id` AS requestid, r1 . *
FROM `Request` AS r1
LEFT JOIN
(SELECT COUNT( * ) AS count, rid
FROM
((SELECT `TwitterTweet`.`id` AS `smid` , `TwitterTweet`.`requestid` AS rid
FROM `TwitterTweet`
WHERE `TwitterTweet`.`requestid` = requestid
AND `TwitterTweet`.`active` =1) AS talias
)) AS Count ON ( Count.rid = requestid )
ORDER BY Count.count
*When I tried to add in the Facebook side it would not compile any more
(The concept is that the results are added from TwitterTweet with the results from FacebookPost
that are attached to the specific requestid which would give us a count. The entire result
set should be ordered by that count)
SELECT r1.`id` AS requestid, r1 . *
FROM `Request` AS r1
LEFT JOIN
(SELECT COUNT( * ) AS count, rid
FROM
((SELECT `TwitterTweet`.`id` AS `smid` , `TwitterTweet`.`requestid` AS rid
FROM `TwitterTweet`
WHERE `TwitterTweet`.`requestid` = requestid
AND `TwitterTweet`.`active` =1 ) AS talias
UNION All
(SELECT `FacebookPost`.`id` AS `smid`, `FacebookPost`.`requestid` AS rid
FROM `FacebookPost`
WHERE `FacebookPost`.`requestid` = requestid
AND `FacebookPost`.`active` = 1) as falias
)) AS Count ON ( Count.rid = requestid )
ORDER BY Count.count
I updated the Query with an attempt to add an alias:
SELECT rid, SUM(count) total_count
FROM
(
(SELECT COUNT(*) AS count, r.rid
FROM request r
JOIN TwitterTweet tt
ON r.id = tt.requestid
WHERE tt.active = 1
GROUP BY r.rid) AS twitter
UNION ALL
(SELECT COUNT(*) AS count, r.rid
FROM request r
JOIN FacebookPost fp
ON r.id = fp.requestid
WHERE fp.active = 1
GROUP BY r.rid ) AS fbook
)
GROUP BY rid
ORDER BY SUM(count) DESC
I made another adjustment to give the middle subquery an alias, but now I only get one row returned with a zero in the rid column and 5686 in the total_count column...the 5686 might be all of the results.
SELECT counts.rid, SUM(count) total_count
FROM
(
SELECT COUNT(*) AS count, r.requestid AS rid
FROM request r
JOIN TwitterTweet tt
ON r.id = tt.requestid
WHERE tt.active = 1
GROUP BY r.requestid
UNION ALL
SELECT COUNT(*) AS count, r.requestid AS rid
FROM request r
JOIN FacebookPost fp
ON r.id = fp.requestid
WHERE fp.active = 1
GROUP BY r.requestid
) AS counts
GROUP BY counts.rid
ORDER BY SUM(count) DESC
Got it!!!
Thanks for your help guys, I had to remove those joins on the request:
SELECT counts.rid, SUM(count) total_count
FROM
(
SELECT COUNT(*) AS count, tt.requestid AS rid
FROM TwitterTweet tt
WHERE tt.active = 1
GROUP BY tt.requestid
UNION ALL
SELECT COUNT(*) AS count, fp.requestid AS rid
FROM FacebookPost fp
WHERE fp.active = 1
GROUP BY fp.requestid
) AS counts
GROUP BY counts.rid
ORDER BY SUM(count) DESC
SELECT id, SUM(count) total_count
FROM
(
SELECT COUNT(*) AS count, r.id
FROM request r
JOIN TwitterTweet tt
ON r.id = tt.requestid
WHERE tt.active = 1
GROUP BY r.id
UNION ALL
SELECT COUNT(*) AS count, r.id
FROM request r
JOIN FacebookPost fp
ON r.id = fp.requestid
WHERE fp.active = 1
GROUP BY r.id
) sub
GROUP BY id
ORDER BY SUM(count) DESC
;