If i have a MYSQL table that sorts names and one table that sorts value.
Example this is how the table look like:
ID name value
-- ------ -----
1 John 500
2 Rock 350
3 Wayne 700
4 John 350
5 Rock 250
6 Nick 100
7 Sweety 75
8 Lex 350
How do i display the total value for eache user? and also if i want to filter it to only show top 3 is there an easy command for that? Or do i need to make some kind of function.
In PHP
John 850
Wayne 700
Rock 600
Lex 350
Nick 100
Sweety 75
It can be accomplished by the aggregates, kind of
SELECT ID, name, SUM(value) as total_score
FROM user_scores
GROUP BY name
ORDER BY total_score
You need an aggregate function, specifically SUM. You can order a query by any value in the select list, and to go high-to-low just use the DESC keyword:
SELECT Name, SUM(value) AS TotalValue
FROM myTable
GROUP BY Name
ORDER BY TotalValue DESC
The AS TotalValue will ensure that the column name is TotalValue when you reference it in PHP.
Related
I have a table sorted like this, example;
name | like
_______________
mark 8
luca 8
giorge 2
delta 3
delta 2
luca 8
mark 3
now I would like;
1 merge results name
2 and then sort, after joining the result from largest to smallest, example;
name | like
_______________
luca 16
mark 11
delta 5
giorge 2
how can I do?
simple group by :
select
name, sum(like) as likecount
from tablename
group by name
order by likecount desc
I'm working on a track and field ranking database in MySQL/PHP5 whereby I'm struggling to find the best way to query results per unique athlete by highest value.
just
SELECT distinct name, event
FROM results
sample database
name | event | result
--------------------------
athlete 1 | 40 | 7.43
athlete 2 | 40 | 7.66
athlete 1 | 40 | 7.33
athlete 1 | 60 | 9.99
athlete 2 | 60 | 10.55
so let's say that in this case I'd like to rank the athletes on the 40m dash event by best performance I tried
SELECT distinct name, event
FROM results
WHERE event = 40
ORDER by result DESC
but the distinct only leaves the first performance (7.43) of the athlete which isn't the best (7.33). Is there an easy way other than creating a temp table first whereby the results are ordered first and performing a select on the temp table afterwards?
You might be interested in group by:
SELECT name, min(result) as result
FROM results
WHERE event = 40
GROUP BY name
This gives you the best result per athlete.
As suggested by spencer, you can also order the list by appending this:
ORDER BY min(result) ASC
The problem is that the columns used in the ORDER BY aren't specified in the DISTINCT. To do this, you need to use an aggregate function to sort on, and use a GROUP BY to make the DISTINCT work.
SELECT distinct name, event
FROM results
WHERE event = 40
GROUP BY name
ORDER by result DESC
let me explain the whole thing with an example:
| id | product | rating |
1 23 54
2 23 54
3 23 53
4 24 33
5 26 22
6 24 11
Lets say we have multiple ratings for each product and want to display the three top products. This would mean we can can user Inner-/left-/right- Join to get the products name from another table, order it by desc and set a limit of 3. But this would show us the same product three times with a rating of 54, 54 and 53.
Is it possible to avoid products with the same id in the result just with SQL?
So the dream output from one SQL query would be:
| id | product | rating |
1 23 54
4 24 33
5 26 22
In words: the top three unique products by rating (and of course only the row of the item with the highest rating -> id 1 or 2 for product 23 and not id 3).
Further more if there is only one product or two products with multiple ratings it should only transfer 1 or 2 results.
You can do this by taking the maximum rating for each product and choosing the top three:
select product, max(rating) as maxrating
from table t
group by product
order by maxrating desc
limit 3;
If you want the id for this rating, you can use the substring_index()/group_concat() trick:
select product, max(rating) as maxrating,
substring_index(group_concat(id order by rating desc), ',', 1) as id
from table t
group by product
order by maxrating desc
limit 3;
Alternatively, you can eschew the group by:
select t.*
from table t
where not exists (select 1
from table t2
where t2.product = t.product and
(t2.rating > t.rating or
t2.rating = t.rating and t2.id > t.id
)
)
order by t.rating desc
limit 3;
The complicated where clause is because multiple ratings can be the same.
EDIT:
The not exists version is getting the highest rating on the highest id for each row. The logic is simply saying: "Get me all rows from the products table where the product in the row has no other row with a higher rating/id combination". This is an awkward way for people to understand "Get the row with the maximum rating". But it turns out to be easier for the database to process. It is typically the most efficient method in MySQL and often the most efficient method in other databases as well, particularly with the right indexes defined.
Use a SELECT DISTINCT query. Check out details here: http://dev.mysql.com/doc/refman/5.6/en/select.html
I have a list of films that users can rank in order of which they like best using jQuery UI Sortable (all works well). The lower the order number the better the film (1) and the higher (26) the worse it is. The list of films could be endless but is fixed in the database (users can't add more), so the user can only select from x list of films.
Films do not have to be in the users list, if they haven't seen film 5 then it won't get included (this may be compounding the problem).
Currently this is stored in the table:
film_id | user_id | order
4 2 3
5 3 3
6 2 1
7 2 2
7 3 1
8 3 2
What I want, and don't know where to start is an overall 'Top 10' style list. i.e. film 7 is the most popular because it appears higher up peoples lists and is in more lists. Film 6 could be the most popular but it's only in one list?!
I am stuck on both the logic and the Mysql queries to do it!
I am thinking I might need to weight the order somehow? Or have a separate table with the score per film and just update it after every edit. The following query seems like the right idea if it was just based on the count of items in the table but not when I want to add position in to the equation.
SELECT ff.film_id, COUNT(ff.film_id) AS cnt, SUM(ff.order) AS rank FROM
`favourite_film` AS ff GROUP BY ff.film_id ORDER BY cnt DESC, rank ASC
I guess I need the count of all the films in the table and the sum of the order (but reversed?), my theory then goes flat!
Any help or links would be greatly appreciated. Thanks.
Depending your "business rules", I think you should find some sort of calculation to both take into account the position and the number of "votes".
Just a random guess, but why not sorting by COUNT(votes)/AVG(pos) ? For maintainability reason, you might want to factor out the ranking function:
CREATE FUNCTION ranking(average_pos REAL, vote_count INT)
RETURNS REAL
DETERMINISTIC
RETURN vote_count/average_pos;
The query is now simply:
SELECT film_id,
AVG(pos) as a, COUNT(*) as c, ranking(AVG(pos),COUNT(*)) AS rank
FROM vote GROUP BY film_id
ORDER BY ranking(AVG(pos), COUNT(*)) DESC;
Producing with your example:
+----------+------+----+----------------+
| FILM_ID | A | C | RANK |
+----------+------+----+----------------+
| 7 | 1.5 | 2 | 1.333333333333 |
| 6 | 1 | 1 | 1 |
| 8 | 2 | 1 | 0.5 |
| 5 | 3 | 1 | 0.333333333333 |
| 4 | 3 | 1 | 0.333333333333 |
+----------+------+----+----------------+
See http://sqlfiddle.com/#!2/3b1d9/1
you should have reverted the list before saving it. this way you could leave the unselected movies out of the rating.
a workaround might be:
Count the amount of lists SELECT COUNT(DISTINCT(user_id) save this as $AMOUNT_OF_LISTS
now count the points using
SELECT film_id, (SUM(order)+($AMOUNT_OF_LISTS-COUNT(DISTINCT(user_id)))*POINTS_FOR_NOT_IN_LIST) as points FROM table GROUP BY film_id
logic: sum up all points and add POINTS_FOR_NOT_IN_LIST points for every time not in a list (total amount of lists - amount of times movie is in the list)
insert a value POINTS_FOR_NOT_IN_LIST to your liking. (might be 26 or 27 or even lower)
you probably want to add ORDER BY points DESC LIMIT 10 to the query to get 10 highest points
SELECT MIN( `order` ) , COUNT( * ) AS cnt, `film_id`
FROM `favourite_film`
GROUP BY `film_id`
ORDER BY cnt DESC , `order`
I would do this, I would assign a higher value to the movies with the higher ranking. Then I would sum the values per movie and order by the total descending to get the overall ranking. This way you are giving weight to both the popularity and rankings of each movie.
So if you wanted to do it by the top 3 ranked movies per user you could do this:
SELECT film_id, SUM(3 -- The max number of ranked movies per user
- order -- the ranking
+ 1) total_score
FROM TABLE_NAME
GROUP BY film_id
ORDER BY total_score DESC;
Obviously you could remove the comments
This way the top rated movie would get the higher score, the next highest, the next highest score, etc. If you were counting the top 10 movies per user, just change the 3 to 10.
I was just wondering that, how to get the greatest number in the table.
I mean i have a table called: hits; in that their are 2 columns:
1. id
2. hit
and their are many ids in the table and all have more than 10 hits, now what i want to do is to get the greatest id of the greatest hit
PS: See below:
id | hit
---|----
1 | 10
2 | 15
3 | 45
4 | 9
yes you can use MAX function to use like below
Select Id,Max(hit) from yourtableName group by id having hit=Max(hit)
Select Id,
Max(Hit)
from tableName
group by id
having Max(hit)=(Select Max(Hit) from TableName)
SQL FIDDLE Demo
Wouldn't it be faster to do this:
SELECT * FROM table WHERE 1 ORDER BY hit DESC, id DESC LIMIT 1
Rather than using MAX, Especially if you have a larger table
http://www.witti.ws/blog/2011/04/06/mysqls-max-slow-5-years-later