MySQL - "Most social User" with the most comments in multiple tables - mysql

I have 2 tables of concern - 'videoComments', 'storyComments'.
I need to find the 'posterID' that has the most entries in videoComments and storyComments. Here's the code I have so far, but it only calls videoComments:
$sql = "SELECT (SELECT posterID
FROM videoComments
GROUP BY posterID
ORDER BY COUNT(posterID) DESC LIMIT 1) ) AS mostSocialUser ";
How do I pull it and compare the COUNT of posterID from both tables?

Use:
SELECT x.posterid,
COUNT(y.posterid) + COUNT(z.posterid) AS numComments
FROM (SELECT vc.posterid
FROM VIDEOCOMMENTS vc
UNION
SELECT sc.posterid
FROM STORYCOMMENTS sc) x
LEFT JOIN VIDEOCOMMENTS y ON y.posterid = x.posterid
LEFT JOIN STORYCOMMENTS z ON z.posterid = x.posterid
GROUP BY x.posterid
ORDER BY numComments DESC
LIMIT 1

Try this:
SELECT (
SELECT posterID FROM (
SELECT posterID FROM videoComments
UNION
SELECT posterID FROM storyComments
) GROUP BY posterID
ORDER BY COUNT(posterID) DESC LIMIT 1
) AS mostSocialUser

Related

Get only 1 result per group of ID

I have a list of records (domestic_helper_idcards) and I want to return only one card per staff (domestic_helper_id) that is not deleted (is_deleted = 0), and that has the card_expiration_date furthest in the future (latest expiry date).
Have tried grouping and so on, but cant get it to work. Code below:
SELECT * FROM domestic_helper_idcard
where
is_deleted = 0
order by card_expiration_date desc
This returns the following (image):
I want only records with ID 4 and 5 to be returned. Anyone?
You could use a join with the subquery grouped by domestic_helper_id with an aggregated function eg: max()
SELECT d.*
FROM domestic_helper_idcard d
inner join (
select domestic_helper_id, max(id) max_id
from domestic_helper_idcard
where is_deleted = 0
group by domestic_helper_id
) t on t.domestic_helper_id = d.domestic_helper_id and t.max_id = d.id
order by d.card_expiration_date desc
and as suggested by Jens after clarification using max card_expiration_date
SELECT d.*
FROM domestic_helper_idcard d
inner join (
select domestic_helper_id, max(card_expiration_date) max_date
from domestic_helper_idcard
where is_deleted = 0
group by domestic_helper_id
) t on t.domestic_helper_id = d.domestic_helper_id and t.max_date = d.max_date
order by d.card_expiration_date desc

Finding top 5 results for multiple values in sql result

I have the following sql query:
SELECT v.venue_id, s.zip, COUNT( * )
FROM bcs_scans s
JOIN bcs_scanners sc ON s.uuid = sc.uuid
JOIN bcs_venues v ON sc.venue_id = v.venue_id
WHERE v.banlist_id = '625'
AND s.del =0
GROUP BY s.zip
ORDER BY COUNT( * ) DESC
Which returns the count of individual zip codes, their count, and associated venue.
How do I go about selecting the top 5 zip codes for each unique venue id?
I believe I can run a subquery that groups results by venue id with the top 5 zip counts, but I am unsure of where to start
Could be you select the result in this way ... a bit complex ..
using the having for extract the value that match the max count group by venue_id from your original query ..
SELECT v.venue_id as venue_id, s.zip as , COUNT( * ) as num
FROM bcs_scans s
JOIN bcs_scanners sc ON s.uuid = sc.uuid
JOIN bcs_venues v ON sc.venue_id = v.venue_id
WHERE v.banlist_id = '625'
AND s.del =0
GROUP BY s.zip
HAVING ( v.venue_id, COUNT( * )) in
(select venue_id, max(num)
from
(SELECT v.venue_id as venue_id, s.zip as , COUNT( * ) as num
FROM bcs_scans s
JOIN bcs_scanners sc ON s.uuid = sc.uuid
JOIN bcs_venues v ON sc.venue_id = v.venue_id
WHERE v.banlist_id = '625'
AND s.del =0
GROUP BY s.zip
ORDER BY COUNT( * ) DESC ) a t
group by venue_id)
ORDER BY COUNT( * ) limit 5

SQL INNER JOIN returning more rows than I need

This is my situation:
I have 2 tables, tickets and tickets-details. I need to retrieve the info inside "tickets" and just the LAST reply from "tickets-details" for each ticket, then show em in a table. My problem is that "ticket-details" returns a row per each reply and I'm getting more than one row per ticket. How can I achieve this in a single query ?
I tried adding DISTINCT into my SELECT but didn't.
I tried using GROUP BY id_ticket but didnt' work too because I wasn't getting the last reply from ticket-details
This is my query:
SELECT DISTINCT ti.id_ticket,ti.title,tiD.Reply,ti.status
FROM tickets ti
INNER JOIN ticket-details tiD ON ti.id_ticket = tiD.id_ticket
WHERE user = '$id_user' ORDER BY status desc
---------------------------------- EDIT-----------------------------------------------
my tables:
tickets(id_ticket, user, date, title, status)
ticket-details(id_ticketDetail, id_ticket, dateReply, reply)
Assuming that the max id_ticketDetail represents the most recent record in ticket-details you can try
SELECT ti.id_ticket,
ti.title,
tiD.Reply,
ti.status
FROM tickets ti JOIN
(
SELECT id_ticket, reply
FROM `ticket-details` d JOIN
(
SELECT MAX(id_ticketDetail) max_id
FROM `ticket-details`
GROUP BY id_ticket
) q ON d.id_ticketDetail = q.max_id
) tiD ON ti.id_ticket = tiD.id_ticket
WHERE ti.user = '$id_user'
ORDER BY ti.status DESC
or a version with max dateReply
SELECT ti.id_ticket,
ti.title,
tiD.Reply,
ti.status
FROM tickets ti JOIN
(
SELECT d.id_ticket, d.reply
FROM `ticket-details` d JOIN
(
SELECT id_ticket, MAX(dateReply) max_dateReply
FROM `ticket-details`
GROUP BY id_ticket
) q ON d.id_ticket = q.id_ticket
AND d.dateReply = q.max_dateReply
) tiD ON ti.id_ticket = tiD.id_ticket
WHERE ti.user = '$id_user'
ORDER BY ti.status DESC
Here is SQLFiddle demo for both queries.
I do not know Your datatabase model, but if ID is autoincremented you can extend your script with this condition:
SELECT ti.id_ticket,ti.title,tiD.Reply,ti.status
FROM tickets ti
INNER JOIN ticket-details tiD ON ti.id_ticket = tiD.id_ticket
WHERE user = '$id_user'
and tiD.id_ticket in (select max(a.id) from ticket-details a group by a.id_ticket)
ORDER BY status desc
Or if you have some kind of date attribute, change new condition to your date attribute (in my example it is ticked_date )
and tiD.ticked_date in (select max(a.ticked_date) from ticket-details a group by a.id_ticket)
If you need to grab a bunch of tickets with their ticket-details, adding a subquery would work (though it's a little inefficient):
SELECT DISTINCT
ti.id_ticket,ti.title,tiD.Reply,ti.status
FROM tickets ti INNER JOIN ticket-details tiD
ON ti.id_ticket = tiD.id_ticket
WHERE user = '$id_user' AND
tiD = (select id from ticket-details where ticket-details.id_ticket = ti.id_ticket ORDER BY ticket-details.date_field DESC LIMIT 1) ORDER BY status desc
If you only need to do this for one ticket at a time, it's as simple as ordering by the date field in ticket-details and throwing a limit in there:
SELECT DISTINCT
ti.id_ticket,ti.title,tiD.Reply,ti.status
FROM tickets ti INNER JOIN ticket-details tiD
ON ti.id_ticket = tiD.id_ticket
WHERE user = '$id_user' ORDER BY tiD.date_field, status DESC LIMIT 1

Subquery with LIMIT in MYSQL complex query

The Mysql version i'm using don't let me use a LIMIT inside subquery so i can speed up the query. How to use join instead in the next query?
SELECT p . * , (
SELECT AVG( review_rating ) AS rating_total
FROM reviews r
WHERE r.review_item_ref = p.pattern_ref
AND r.review_state =1
GROUP BY r.review_item_ref
) AS review_rating
FROM patterns p
WHERE pattern_active >=0
AND p.pattern_family =27
AND p.pattern_ref
IN (
SELECT item_pattern_ref
FROM items
WHERE item_pattern_ref = p.pattern_ref LIMIT 1
)
GROUP BY p.pattern_id
ORDER BY p.pattern_description ASC , LCASE( p.pattern_description ) ASC
LIMIT 0 , 16
Looks like you're trying to validate that p.pattern_ref has a match in items, is that correct?
If so,
SELECT
p . *,
(SELECT AVG( review_rating ) AS rating_total
FROM reviews r
WHERE r.review_item_ref = p.pattern_ref
AND r.review_state =1
GROUP BY r.review_item_ref
) AS review_rating
FROM patterns p
INNER JOIN items i ON p.pattern_ref = i.item_pattern_ref
WHERE p.pattern_active >= 0
AND p.pattern_family = 27
GROUP BY p.pattern_id
ORDER BY p.pattern_description ASC , LCASE( p.pattern_description ) ASC
LIMIT 0 , 16
should work. INNER JOIN will only return rows where both sides have a match.
You can't use LIMIT in a subquery.

What's wrong on this query?

I'm selecting total count of villages, total count of population from my tables to build statistics. However, there is something wrong. It returns me everything (530 pop (there are 530 pop in total), (106 villages (there are 106 users in total)) in first row, next rows are NULLs
SELECT s1_users.id userid, (
SELECT count( s1_vdata.wref )
FROM s1_vdata, s1_users
WHERE s1_vdata.owner = userid
)totalvillages, (
SELECT SUM( s1_vdata.pop )
FROM s1_users, s1_vdata
WHERE s1_vdata.owner = userid
)pop
FROM s1_users
WHERE s1_users.dp >=0
ORDER BY s1_users.dp DESC
Try removing s1_users from inner SELECTS
You're already using INNER JOINs. Whan you list tables separated with comma, it is a shortcut for INNER JOIN.
Now, the most obvious answer is that your subqueries using aggregating functions (COUNT and SUM) are missing a GROUP BY clauses.
SELECT s1_users.id userid, (
SELECT count( s1_vdata.wref )
FROM s1_vdata, s1_users
WHERE s1_vdata.owner = userid
GROUP BY s1_vdata.owner
)totalvillages, (
SELECT SUM( s1_vdata.pop )
FROM s1_users, s1_vdata
WHERE s1_vdata.owner = userid
GROUP BY s1_vdata.owner
)pop
FROM s1_users
WHERE s1_users.dp >=0
ORDER BY s1_users.dp DESC
However, using subqeries in column list is really inefficient. It casues subqueries to be run once for each row in outer query.
Try like this instead
SELECT
s1_users.id AS userid,
COUNT(s1_vdata.wref) AS totalvillages,
SUM(s1.vdata.pop) AS pop
FROM
s1_users, s1_vdata --I'm cheating here! There's hidden INNER JOIN in this line ;P
WHERE
s1_users.dp >= 0
AND s1_users.id = s1_vdata.owner
GROUP BY
s1_users.id
ORDER BY
s1_users.dp DESC
SELECT s1_users.id AS userid,
(
SELECT COUNT(*)
FROM s1_vdata
WHERE s1_vdata.owner = userid
) AS totalvillages,
(
SELECT SUM(pop)
FROM s1_vdata
WHERE s1_vdata.owner = userid
) AS pop
FROM s1_users
WHERE dp >= 0
ORDER BY
dp DESC
Note that this is less efficient than this query:
SELECT s1_users.id AS user_id, COUNT(s1_vdata.owner), SUM(s1_vdata.pop)
FROM s1_users
LEFT JOIN
s1_vdata
ON s1_vdata.owner = s1_users.id
GROUP BY
s1_users.id
ORDER BY
dp DESC
since the aggregation needs to be done twice in the former.
SELECT userid,totalvillages,pop from
(
SELECT s1_users.id as userid, count( s1_vdata.wref ) as totalvillages
FROM s1_vdata, s1_users
WHERE s1_vdata.owner = userid
GROUP BY s1_users.id) tabl1 INNER JOIN
(
SELECT s1_users.id as userid, SUM( s1_vdata.pop ) as pop
FROM s1_users, s1_vdata
WHERE s1_vdata.owner = userid
GROUP BY s1_users.id) tabl2 on tabl1.userid = tabl2.userid