How to get rank based on SUM's? - mysql

I have comments table where everything is stored, and i have to SUM everything and add BEST ANSWER*10.
I need rank for whole list, and how to show rank for specified user/ID.
Here is the SQL:
SELECT m.member_id AS member_id,
(SUM(c.vote_value) + SUM(c.best)*10) AS total
FROM comments c
LEFT JOIN members m ON c.author_id = m.member_id
GROUP BY c.author_id
ORDER BY total DESC
LIMIT {$sql_start}, 20

How about something like this:
SET #rank=0;
SELECT * FROM (
SELECT #rank:=#rank+1 AS rank, m.member_id AS member_id,
(SUM(c.vote_value) + SUM(c.best)*10) AS total
FROM comments c
LEFT JOIN members m ON c.author_id = m.member_id
GROUP BY c.author_id
ORDER BY total DESC
) as sub
LIMIT {$sql_start}, 20

You may want to check out windowing functions if your MySQL version supports them...
SELECT m.member_id AS member_id,
(SUM(c.vote_value) + SUM(c.best)*10) AS total,
RANK() OVER (ORDER BY (SUM(c.vote_value) + SUM(c.best)*10)) as ranking
FROM comments c
LEFT JOIN members m ON c.author_id = m.member_id
GROUP BY c.author_id
ORDER BY total DESC;
Another possibility is this:
SELECT m.member_id AS member_id,
(SUM(c.vote_value) + SUM(c.best)*10) AS total,
(SELECT count(distinct <column you want to rank by>)
FROM comments c1
WHERE c1.author_id = m.member_id) as ranking
FROM comments c
LEFT JOIN members m ON c.author_id = m.member_id
GROUP BY c.author_id
ORDER BY total DESC;
NB: There's a lot of open questions around this, but the above two techniques are simple methods to determine rankings in general. You'll want to change the above to fit your exact need, as I'm a little fuzzy on what constitutes the rank for a member_id.

SELECT
#rank:=#rank+1 as rank,
m.member_id AS member_id,
(SUM(c.vote_value) + SUM(c.best)*10) AS total
FROM comments c,
(SELECT #rank:=0) as init
LEFT JOIN members m ON c.author_id = m.member_id
GROUP BY c.author_id
ORDER BY total DESC
LIMIT {$sql_start}, 20
In the solution, ranks are always increasing even if total is the same.

Related

How to fix this code? i tried WITH statement but it gave me an error

I tried to answer this question here in the code below, but it keeps giving me an error message!
I've tried to figure out how to
Provide the name of the sales_rep in each region with the largest amount of total_amt_usd sales?
and it gave me this Error :
aggregate function calls cannot be nested
ERD picture here
could you please help me with this?
WITH
account_info AS (Select * from accounts),
orders_info AS (select * from orders),
region_info AS (select * from region),
sales_reps_info AS (select * from sales_reps)
SELECT s.name as rep_name, r.name as region_name, MAX (SUM (o.total_amt_usd)) as total
FROM orders_info o
JOIN account_info a
ON o.account_id = a.id
JOIN sales_reps_info s
ON a.sales_rep_id = s.id
JOIN region_info r
ON r.id = s.region_id
GROUP BY TOTAL, REP_NAME, R.NAME
ORDER BY 3 DESC
When you are using the whole table there is no need for WITH
SELECT s.name as rep_name, r.name as region_name, MAX (SUM (o.total_amt_usd)) as total
FROM orders o
JOIN account a
ON o.account_id = a.id
JOIN sales_reps s
ON a.sales_rep_id = s.id
JOIN region r
ON r.id = s.region_id
GROUP BY TOTAL, REP_NAME, R.NAME
ORDER BY 3 DESC
LIMIT 100;
I'm not sure what you are attempting with with since you don't actually define a Common Table Expression.
That aside, your query is invalid, you cannot nest aggregate functions and you are already getting the max 100 by ordering and limiting rows, so I think you just want
SELECT s.name as rep_name, r.name as region_name, SUM (o.total_amt_usd) as Total
FROM orders_info o
JOIN account_info a ON o.account_id = a.id
JOIN sales_reps_info s ON a.sales_rep_id = s.id
JOIN region_info r ON r.id = s.region_id
GROUP BY REP_NAME, R.NAME
ORDER BY Total DESC
LIMIT 100;

MySQL Group Join Table

I have below three SQL statement and I want to select out like below, I tried but not success.
Need some
help.
Output:
member_id, balance, firstname, lastname, LastPurchase, LastOrde
SELECT c.member_id
, c.firstname
, c.lastname
, m.balance
FROM member m
, customer c
where m.member_id = c.member_id
order
by m.member_id
SELECT member_id, max(date) as LastPurchase
FROM purchase
GROUP
BY member_id
SELECT member_id, max(date) as LastOrder
FROM ordert
GROUP
BY member_id
You can join these statements -
SELECT c.member_id, c.firstname, c.lastname, m.balance, p.LastPurchase, o.LastOrder
FROM member m
join customer c on m.member_id = c.member_id
left join (SELECT member_id, max(date) as LastPurchase
FROM purchase
GROUP BY member_id) p on p.member_id = m.member_id
left join (SELECT member_id, max(date) as LastOrder
FROM ordert
GROUP BY member_id) o on o.member_id = m.member_id
order by m.member_id
You can join the aggregate queries. The JOIN ... USING syntax comes handy here, since all join column names are the same:
SELECT c.member_id, c.firstname, c.lastname, m.balance, p.last_purchase, o.last_purchase
FROM member m
INNER JOIN customer c USING(member_id)
INNER JOIN (
SELECT member_id, max(date) last_purchase FROM purchase GROUP BY member_id
) p USING(member_id)
INNER JOIN (
SELECT member_id, max(date) last_order FROM order GROUP BY member_id
) o USING(member_id)
ORDER BY c.member_id
Important: your original query uses implicit, old-shool joins (with a comma in the from clause) - this syntax fell out of favor more than 20 years ago and its use is discourage, since it is harder to write, read, and understand.
One of the many benefits of using explicit joins here is that you can easily change the INNER JOINs to LEFT JOINs if there is a possibility that a member has no purchase or no order at all.

SQL query with DESC do not working properly

I don't understund why sorting didin't work correctly with "ORDER BY average, votes DESC", because i need highest average and votes are going from the top to bottom, but DESC didin't solve what thing. My result in var_dump http://pastie.org/private/b05smuh0fvw72wwp2w1zq highest entrie is in the bottom, but i need start from the top and going to the bottom.
SELECT c.*, r.votes, c.total_comments,
ROUND(sumrate / votes) AS average
FROM catalog c LEFT JOIN
(SELECT r.object_id, COUNT(*) as votes, SUM(r.rate) as sumrate
FROM ratings r
GROUP BY r.object_id
) r
ON r.object_id = c.catalog_id LEFT JOIN
(SELECT c.catalog_id, COUNT(*) as total_comments
FROM comments c
GROUP BY c.catalog_id
) c
ON c.catalog_id = c.catalog_id
GROUP BY c.catalog_id
ORDER BY average, votes DESC;
Because you can define the order for every column and not just the order by in total. The default is ASC.
Your order
ORDER BY average, votes DESC
turn automatically into
ORDER BY average ASC, votes DESC
But you are looking for
ORDER BY average DESC, votes DESC
You need to specify DESC for both the columns. Otherwise by default it is ASC
SELECT c.*, r.votes, c.total_comments,
ROUND(sumrate / votes) AS average
FROM catalog c LEFT JOIN
(SELECT r.object_id, COUNT(*) as votes, SUM(r.rate) as sumrate
FROM ratings r
GROUP BY r.object_id
) r
ON r.object_id = c.catalog_id LEFT JOIN
(SELECT c.catalog_id, COUNT(*) as total_comments
FROM comments c
GROUP BY c.catalog_id
) c
ON c.catalog_id = c.catalog_id
GROUP BY c.catalog_id
ORDER BY average DESC, votes DESC;

Getting the rank based on the column

I have a MySQL query where I want to add a rank column.
SELECT AM.* , count(ALM.id) as likes FROM admin_models as AM
left join admin_liked_models as ALM on AM.id = ALM.admin_model_id
group by AM.id
admin_models and admin_liked_models has a one to many relationship.
The highest likes should be rank 1.
Can anyone point me out how to do this? Thanks!
Unfortunately MySQL doesn't support Row_Number() or other analytic functions. Here is one way to produce the same results though:
SELECT *,
#rn:=#rn+1 rn
FROM (
SELECT AM.* , count(ALM.id) as likes
FROM admin_models as AM
LEFT JOIN admin_liked_models as ALM ON AM.id = ALM.admin_model_id
GROUP BY AM.id
) t, (SELECT #rn:=0) t2
ORDER BY likes DESC
You probably don't need the subquery, but I'm just showing the separation.
this only works when using with ORDER BY is it not possible to make the rank column based on the number of likes column?
It looks you are not looking for rank. If you do not want to use ORDER and want to use the rank as some grade, you can try something like this:
SELECT AM.* , count(ALM.id) as likes,
((SELECT max(maxval) from
(SELECT count(ALM.id) as maxval FROM admin_models as AM
left join admin_liked_models as ALM on AM.id = ALM.admin_model_id
group by AM.id) as subq) - count(ALM.id) + 1) as rank
FROM admin_models as AM
left join admin_liked_models as ALM on AM.id = ALM.admin_model_id
group by AM.id
Please note that in this case the grade will not be sequential, and several models will have the same grade.

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