i have a currently listening box on the homepage of my music website, and i have a table like this:
id,userid,songid,time
now every time a user plays a song, the id of the song is inserted into the songid field and also the time. so sometimes i have duplicate songid (inserted by different users).
Now here is my sql statement:
SELECT DISTINCT songid,time FROM songs ORDER BY time DESC LIMIT 10
that gives me the last ten songs that were listened, however sometimes it returns duplicate data too! how can i fix this problem? Thanks in advance
You'll want to aggregate over songid:
SELECT songid, MAX(time) AS most_recent_time
FROM songs
GROUP BY songid
ORDER BY most_recent_time DESC
LIMIT 10
If the time is the datetime the song was last played, you can group the gons with the last time each was played:
SELECT songid,MAX(time)
FROM songs
GROUP BY songid
ORDER BY time DESC
LIMIT 10
SELECT *
FROM songs s
WHERE id =
(
SELECT id
FROM songs si
WHERE si.songid = s.songid
ORDER BY
si.songid DESC, si.time DESC, si.id DESC
LIMIT 1
)
ORDER BY
time DESC, id DESC
LIMIT 10
Create the following indexes:
songs (songid, time, id)
songs (time, id)
for this to work fast.
Unlike the GROUP BY songid solutions, this does not require a full table scan or a full index loose scan on songs.
Related
I have been trying to do this for a while, but I might be thinking completely wrong here.
I have a table called songs with ID, Artist, play_count and a table called info with ID, length_seconds.
I want to make a query that sums length_seconds * play_count for each individual track.
I wrote this query, which is wrong.
SELECT Artist
, sum(play_count) AS total_plays
, sum(play_count) * length_seconds as play_length
, count(*) as count
FROM songs
, info
WHERE songs.ID = info.ID
GROUP
BY artist
ORDER
BY total_plays DESC
This query only takes into account the length of the first track. So if the data is like this
ID Artist play_count
1 Artist 2
2 Artist 2
ID length_seconds
1 10
1 100
The output of my query will be
Artist 4 40 2
While I want to it be
Artist 4 220 2
How could I rewrite this query so that it takes into account the length of each track individually?
SELECT Artist, sum(play_count) AS total_plays, sum(play_count * length_seconds) as play_length, count(*) as count FROM songs, info WHERE songs.ID = info.ID GROUP BY artist ORDER BY total_plays DESC
I have table in MySQL DB which contains among other things two fields user_id and score. This table is kind of log table so there can be multiple rows for one user_id with different scores. How can I get only top 10 users with highest score from this table?
SELECT DISTINCT user_id
FROM your_table
ORDER BY score DESC
LIMIT 10
EDIT:
SELECT DISTINCT *
FROM your_table
WHERE (user_id, score) IN (SELECT user_id, MAX(score) AS score
FROM your_table
GROUP BY user_id)
ORDER BY score DESC
LIMIT 10
SqlFiddleDemo
This is basic and you should put more effort; here is atemplate you can use -
SELECT TOP 10 distinct *
FROM people
WHERE names='SMITH'
ORDER BY names asc
I'm trying to write a query which will get the maximum scores for the most popular songs, in order of song popularity.
I have a table called "gameplay" with the following fields:
id
song_id
score
(plus some other arbitrary fields)
So far, the closest I've got is this:
SELECT id, song_id, score
FROM (
SELECT id, song_id, score
FROM (
SELECT id, song_id, score
FROM gameplay
ORDER BY score DESC
) AS all_scores_in_order
GROUP BY song_id
) AS top_scores_per_song
ORDER BY FIELD (song_id, 3,1,2)
But I would like the values in ORDER BY FIELD to be generated by another subquery - the song_id ranked by popularity (in order of counting row occurrences in table) ie.
SELECT song_id
FROM gameplay
GROUP BY song_id
ORDER BY count( id ) DESC
Can't you just group and then order by Count(id) in the outer query?
This should show all sorts sorted by the number of occurrences, and showing the max score:
SELECT song_id, COUNT(id), MAX(score)
FROM gameplay
GROUP BY song_id
ORDER count(id) DESC
Or do you want each song_id to appear several times?
I have a table with feilds : file_id, rating, user_id
There is one rating per user_id, so there could be many rating (in scale of 0-5) for a single file_id.
I want to find avg of ratings for every file_id and then display 5 file_id with highest avg rating.
Actually my sql query looks like:
SELECT m.server_domain, m.original_name, m.type, m.title, m.views,
m.description, m.hash, AVG(mr.rating_scale5) as avg_rating_scale5
FROM c7_media m, c7_storage s, c7_media_ratings mr
WHERE s.public=1 AND m.storage_hash = s.hash AND m.hash = mr.media_hash
GROUP BY mr.media_hash
How should I do this?
Zeeshan
Group by a file_id and then simply order by the average. Cut off all records that fall below the top 5.
SELECT
file_id, AVG(rating) as avg_rating
FROM
table
GROUP BY
file_id
ORDER BY
avg_rating DESC
LIMIT 5
SELECT `file_id`, AVG(`rating`) as a FROM `table`
GROUP BY `file_id` ORDER BY a DESC LIMIT 5
Replace 'table' with the name of your table.
I have an application that tracks high scores in a game.
I have a user_scores table that maps a user_id to a score.
I need to return the 5 highest scores, but only 1 high score for any specific user.
So if user X has the 5 highest scores on a purely numerical basis, I simply return the highest one and then the next 4 user scores.
I have tried to use:
SELECT user_id, score
FROM user_scores
ORDER BY score DESC
GROUP BY user_id
LIMIT 5
But it seems that MySQL drops any user_id with more than 1 score.
This should work:
SELECT user_id, MAX(score)
FROM user_scores
GROUP BY user_id
ORDER BY MAX(score) DESC
LIMIT 5
SELECT user_id, MAX(score) AS score
FROM user_scores
GROUP BY user_id
ORDER BY score DESC
LIMIT 5
Should do the job for you... though don't forget to create indexes...
You can't group by without a summary-function (SUM, COUNT, etc.)
The GROUP BY clause says how to group the SUMs or COUNTs.
If you simply want to break the long list into bunches with a common value, that's not SQL. That's what your application has to do.
Can you use the Distinct operator to say
SELECT DISTINCT(user_id), score
FROM user_scores
ORDER BY score DESC
LIMIT 5
didn't test so not sure if that will definitely work
Returning only the maximum score for a given user is something like the following.
SELECT user_id, max(score) FROM user_scores
GROUP BY user_id
I don't know whether it was a lack of caffeine or just brain explosion, but the answers here were so easy.
I actually got it working with this monstrosity:
SELECT s1.user_id,
(SELECT score FROM user_scores s2 WHERE s2.user_id = s1.user_id ORDER BY score DESC LIMIT 1) AS score
FROM user_scores s1
GROUP BY s1.user_id
ORDER BY s1.score DESC
LIMIT 5