I have a table called photos that has hundred of thousands of user uploaded photos.
Each user can obviously upload several photos.
The table schema is:
id,
user_id,
photo,
date_created
I just want to get the latest record that each user_id has posted..
I tried:
SELECT * FROM photos
GROUP BY user_id
ORDER BY date_created desc LIMIT 300
But that is obviously bringing back a lot of strange results.
This seems like an easy query, but I have done hours and hours of research on stack overflow and reading so many different articles on Google, and I can't for the life of me figure this simple query out.
This should get you the latest row for every user:
SELECT p.user_id, photo, date_created FROM photos p
JOIN (
SELECT user_id, MAX(date_created) max_date FROM photos GROUP BY user_id
) max_dates ON p.user_id = max_dates.user_id AND p.date_created = max_dates.max_date
Sample SQL Fiddle
Check this out. I used HAVING MAX(date_created) to retrieve the records which are currently created/uploaded.
SELECT user_id
FROM photos
GROUP BY user_id
HAVING MAX(date_created)
ORDER BY date_created DESC LIMIT 300
I believe what you want is to get rid of that GROUP BY and use a regular 'WHERE user_id = 'something', being the rest correct.
I tried a query like yours and the result was only one record by each 'user_id', lets say. GROUP BY usually uses a WHERE in the sentence...
http://www.w3schools.com/sql/sql_groupby.asp
I hope that helps :) If you get an error, please post it.
select p1.user_id, p1.photo, p1.date_created
from photos p1 left join photos p2
on p1.id < p2.id and p1.user_id = p2.user_id
where p2.id is null
try that
EDIT
forgot table name, my bad. added it in. also, here's a fiddle to see: http://sqlfiddle.com/#!9/a72f6/3
Related
Suppose I have two tables, users and posts. Posts has the following fields, userid, postid, etc and userid can appear multiple times as one user can write multiple posts....I'm just trying sort the users table based off the # of occurrences per userid in the posts table. I can get the # of occurrences per user using this
SELECT userid, COUNT(*)
FROM posts
GROUP BY userid;
I would like to use the values under COUNT(*) column, maybe add it to my other table because then I can simply to something like this
SELECT * FROM users
ORDER BY newcolumn ASC;
but I'm having trouble doing that. Or can I do it without having to add an extra column? Hints please. Thanks
Left join is the key here!
SELECT users.userid,count(posts.userid) AS total_count
FROM users
LEFT JOIN posts on posts.userid = users.userid
GROUP BY users.userid
ORDER BY total_count DESC;
We are taking the left join on two tables with same user_id and we are counting the total number of posts per user using group by. Finally sort by count and show results.
try an left join:
select users.userid, [user fields],count(postid) as posts_count
from users
left join posts on posts.userid = users.userid
group by users.userid,[user fields]
order by posts_count desc.
You want to select users (FROM users) but you want to sort based on criteria in another table (COUNT(*) FROM posts) -- therefore you need to use a JOIN
Off-hand I can't seem to recall if "JOIN" or "RIGHT JOIN" or "FULL JOIN" is what you need if you wanted to get a cartesian product of the tables then group and aggregate on a single field, but I can avoid the need to remember with a subquery (hopefully someone will soon post a smaller and smarter answer):
SELECT users.* FROM users
JOIN (
SELECT userid, COUNT(*) as count
FROM posts
GROUP BY userid
) as subquery ON users.id = subquery.userid
ORDER BY subquery.count
Note: I haven't tested this query, but it looks good to me. Again: hopefully someone will post a better answer soon as I'm not doing my due dilligence, but you definitely need a JOIN :)
You could add a post_count column to the users table, but you would also have to update that count column every time a user creates a new post and you would have to build that logic into your application.
Otherwise, it looks like the answer from FallAndLearn will get you what you need.
I want to get records after a certain record, say id is 4.
Actually I want to show posts based on likes with pagination.
So I sorted result by likes.
But I don't know how to get the next records based on id.
Here is my code
SELECT urp.* , likes
FROM user_related_posts urp
JOIN (
SELECT post_id, COUNT(*) AS likes
FROM post_likes
WHERE STATUS =1
GROUP BY post_id
) v ON urp.post_id = v.post_id
GROUP BY post_id
ORDER BY likes DESC
LIMIT 0 , 30
Sorry I don't put image, I don't have enough credentials.
What here doing is when I order with likes, ids are unsorted,
but I want records based on id.
You can use LIMIT so that you can retrieve it like pagination
You can use date_created in your query.
SELECT *
FROM post_likes
WHERE (date_created >
(SELECT date_created
FROM post_likes AS p1
WHERE (id= 4)))
Note :
I have not added the entire code.Please use the code and edit as your requirement.
I'm trying to build a simple forum as a learning exercise. At the moment I have a topics(questions) table and a posts table (where the post_thread_id refers to the topic id).
I want to display the topics in the order by which the most recent post in that topic appears. Looking online I used this command:
SELECT topics.topic_title, topics.topic_date, topics.topic_title, max( posts.post_date )
FROM topics
LEFT OUTER JOIN posts ON topics.topic_id = posts.post_thread_id
GROUP BY topics.topic_id
ORDER BY MAX( posts.post_id ) ASC
which seems to work. But it doesn't work if there are no posts linked to a topic (i.e. an empty topic) as NULL comes first every time. I want it so that if no posts exist then the topic date is used to order.
How do I select the topic date if there are no posts?
Thanks (I'd appreciate a simple explanation as to how it is working as I am trying to learn).
ORDER BY
CASE WHEN MAX( posts.post_id ) IS NULL THEN 1 ELSE 0 END ASC
Self explanatory,when MAX(post_Id) is null it will change the order priority.
This question could asked somewhere before but I could not find it, anyways.
So I have a video record that has many comments, each comment belongs to a user. The user on the other hand has many user friends.
Now, when user X signs in and view video Y I want to display the comments of his friends first (ordered by most recent). Then list other comments ordered with most recent.
I would prefer to make this logic in one single query if possible.
Thanks,
In your ORDER BY, do something like the following. Please know that I have know idea what your schema looks like, so this query won't work. But just create a 1/0 value indicating whether or not the user is a friend, and then order by that first, and then order by the posting / comment id afterwards
SELECT
posting.id,
IF(a.friend_id = b.criteria, 1, 0) AS is_friend
...
ORDER BY is_friend DESC, posting.id DESC
How about this
Select comment of friends of X on video Y order by date
Union
Select comment on video Y where they is not friend of X order by date
Use UNION.
(
SELECT 1 AS sort,*
FROM comments
INNER JOIN friends ON comments.poster_id=friends.friend_id
WHERE friends.id='123'
)
UNION
(
SELECT 2 AS sort,*
FROM comments
WHERE poster_id NOT IN(SELECT friend_id FROM friend WHERE id='123')
)
ORDER BY sort,time DESC
So my database setup is fairly simple.
I have a forum_cat table (a forum category) and forum_post table.
The forum_post has a field fk_forum_cat_id which ties each forum post to a category.
Each forum_post also has a field fk_parent_forum_post_id which basically says it belongs to an original post.
Further more, there is a date_added and date_edited field in forum_post.
Now, I am trying to generate the front page for my forum. I want to show a list of forum categories. Each one category should have a post count and the latest post. Could someone give me some direction with a query that does that all in one. I don't want to run 20 separate queries!
If I read your question correctly, you are seeking the category, the count of posts in the category, and the latest post in that category. Perhaps this simplification of laurent-rpnet's answer will do the trick...
SELECT c.forum_cat_id,
COUNT(p.fk_forum_cat_id),
MAX(p.date_added),
(SELECT p2.post_title
FROM forum_post AS p2
WHERE p2.forum_cat_id = c.forum_cat_id
ORDER BY date_added DESC
LIMIT 1)
FROM forum_cat AS c INNER JOIN
forum_post AS p ON p.fk_forum_cat_id = c.forum_cat_id
GROUP BY c.forum_cat_id;
If forum_post primary key is auto-incremented (should be but we never know...), this will return what you need:
SELECT c.forum_cat_id, COUNT(p.fk_forum_cat_id), MAX(p.date_added),
(SELECT p2.post_title FROM forum_post AS p2
WHERE p2.forum_post_id = (SELECT MAX(p3.forum_post_id) FROM forum_post AS p3
WHERE p3.fk_forum_cat_id = p2.fk_forum_cat_id) AND p2.fk_forum_cat_id = c.forum_cat_id)
FROM forum_cat AS c INNER JOIN
forum_post AS p ON p.fk_forum_cat_id = c.forum_cat_id
GROUP BY c.forum_cat_id;
I had to guess some field names:
forum_cat_id = forum _cat primary key
forum_post_id = forum_post primary key
post_title = post title or begining of post text in forum_post (depends on what you want to show).
The COUNT(p.fk_forum_cat_id) column will contain the post count in category
In addition to what you asked, you will get the date of the lastest post in the category as I think you'll need it if it is a good forum ;).
Obs: I didn't test it so you may need some debugging. If you have problems, let me know.
You can adapt this example to your problem:
SELECT *
FROM `test_post` AS p3
JOIN (
SELECT MAX( id ) AS id
FROM `test_post` AS p1
JOIN (
SELECT MAX( `test_post`.date ) AS DATE, cat
FROM `test_post`
GROUP BY cat
) AS p2 ON p1.date = p2.date
AND p1.cat = p2.cat
GROUP BY p1.cat
) AS p4 ON p3.id = p4.id;
Queries to dynamically count things tend to get slow very quickly and consume a lot of cpu. Even with good indexes, MySQL has to do a lot of work every single time to count all those rows.
An alternative to a query like this would be to summarize the counts of posts in the forum_cat table. Create a column named something like posts_count. Every time a post is created, it's easy enough to run a query increment or decrement the count.
UPDATE forum_cat SET posts_count=posts_count+1;
When you go to create the front page, your query becomes much more simple, and performant.