How can order by last replies? - sql

I have two tables the first is the 'users' the second is the 'posts',
the 'users' have two columns:
1 id
2 username
the 'posts' have five columns:
1 p_id
2 uid
3 post_id
4 content
5 date
the posts as defined have the value '0' in post_id and the replies have the value p_id in post_id. My query is
SELECT id,username,p_id,uid,post_id,content,date
FROM users
inner join posts
ON users.id=posts.uid
WHERE post_id='0'
ORDER BY p_id DESC
but I want to order by the last replies like in a forum.

Use a correlated subquery in the SELECT clause to find the latest reply date and order by that column. If the post has no replys, use the date of the post instead:
SELECT id,username,p_id,uid,post_id,content,date, (
SELECT MAX(date) FROM posts r WHERE r.post_id = p.p_id
) AS last_reply_date
FROM users
inner join posts p
ON users.id=p.uid
WHERE p.post_id='0'
ORDER BY COALESCE(last_reply_date, p.date) DESC

Related

GROUP BY with ORDER BY / last post_time

I have a list of writers in a topic. The List shows the writers name a the last post time inside this topic.
A member can also write more frequently in the topic. Therefore a "group by" was set on the poster_id.
The whole list should be sorted according to the write date. The newest comes first. So I placed maxtime DESC.
Problem:
The list output is working very well but the date of a writer's last post is not the last post_time but always the first post_time.
Table "USERS":
user_id
username
1
Marc
2
Paul
3
Sofie
4
Julia
Table "POSTS"
post_id
topic_id
poster_id
post_time
4565
6
1
999092051
4567
6
4
999094056
4333
6
2
999098058
7644
6
1
999090055
This is my query:
SELECT
p.poster_id,
p.post_time,
p.post_id,
Max(p.post_time) AS maxtime,
u.user_id,
u.username,
FROM POSTS as p
INNER JOIN USERS as u ON u.user_id = p.poster_id
WHERE p.topic_id = 6
GROUP BY p.poster_id
ORDER BY maxtime DESC
How is it possible to display the last post_time of the poster_id instead the first one.
Using columns in Select which are not in group by or in an aggregation function is in most db's forbiden, becuase it is not defined which values are shown.
You can use a subquery with group by and having
SELECT
p.poster_id,
p.post_time,
p.post_id,
p.topic_id,
u.user_id,
u.username
FROM posts as p
INNER JOIN users as u ON u.user_id = p.poster_id
where p.topic_id = 6 AND (p.poster_id, p.post_time )in(select poster_id, max(post_time) from posts group by poster_id )
Demo
The problem with your query is that all your non-aggregated fields must be present inside the GROUP BY clause. As long as this condition is not met, you either have an error fired by your DBMS, or expect some subtle output mistakes. Additionally your query would fire a syntax error due to the comma after the last selected field in the SELECT clause.
If you're using MySQL 8.0, you can use the ROW_NUMBER window function to select your last post time for each poster (rownum = 1, partitioned by poster, ordered by post_time desc), then join back to your users table to get information.
WITH topic_id6 AS (
SELECT poster_id, post_time, post_id, topic_id,
ROW_NUMBER() OVER(PARTITION BY topic_id, poster_id ORDER BY post_time DESC) AS rn
FROM POSTS
)
SELECT id6.poster_id, id6.post_time, id6.post_id, id6.topic_id, u.*
FROM topic_id6 id6
INNER JOIN USERS u
ON id6.poster_id = u.user_id
AND id6.rn = 1
Check the demo here.

postgreSQL doesn't order by

I have this postgreSQL query, which is supposed to be
returning
top 3 comments ordered by comment_date from
top 10
posts table ordered by post_date...
for some reason it's not ordering by post_date:
with a as
(
SELECT
posts.post_id as post_id
FROM posts where user_id = 'user1'
order by post_date desc --this is not working
limit 10
), b as
(
select user_id,
comment_id,
post_id,
comment_date
, ROW_NUMBER() over (partition by post_id order by comment_date desc) as RowNum
from post_comments
)
SELECT * from a
INNER JOIN b USING (post_id)
where b.RowNum <= 3
example: https://extendsclass.com/postgresql/434e9d2
in the example it should be getting the post which has the highest post_date so like this post3>post2>post1
but the ordering of posts is not working...
I'm new to postgreSQL so i don't have any idea what's happening... actually i got that query from a stackoverflow answer just edited it a little bit: Answer
Thanks for answering and sorry for my bad english
The ordering is just fine. How do I know? The outer query has no order by. Without an order by the results can be in any order.
If you want results in a particular order, then you need to be explicit:
SELECT *
FROM a JOIN
b USING (post_id)
WHERE b.RowNum <= 3
ORDER BY a.post_date DESC;
Note: You'll need to include post_date in the a CTE.

Select rows where the last row of associated table has a specific value

I have two tables:
User (id, name)
UserEvent (id, user_id, name, date)
How can I get all the users where the last (ordered by date) UserEvent.name has a value of 'played'?
I wrote an example on SQLFiddle with some specific data: http://sqlfiddle.com/#!9/b76e24 - For this scenario I would just get 'Mery' from table User, because even though 'John' has associated events name of the last one is not 'played'.
This is probably fastest:
SELECT u.*
FROM usr u -- avoiding "User" as table name
JOIN LATERAL (
SELECT name
FROM userevent
WHERE user_id = u.id
ORDER BY date DESC NULLS LAST
LIMIT 1
) ue ON ue.name = 'played';
LATERAL requires Postgres 9.3+:
What is the difference between LATERAL and a subquery in PostgreSQL?
Or you could use DISTINCT ON (faster for few rows per user):
SELECT u.*
FROM usr u -- avoiding "User" as table name
JOIN (
SELECT DISTINCT ON (user_id)
user_id, name
FROM userevent
ORDER BY user_id, date DESC NULLS LAST
) ue ON ue.user_id = u.id
AND ue.name = 'played';
Details for DISTINCT ON:
Select first row in each GROUP BY group?
SQL Fiddle with valid test case.
If date is defined NOT NULL, you don't need NULLS LAST. (Neither in the index below.)
PostgreSQL sort by datetime asc, null first?
Key to read performance for both but especially the first query is a matching multicolumn index:
CREATE INDEX userevent_foo_idx ON userevent (user_id, date DESC NULLS LAST, name);
Optimize GROUP BY query to retrieve latest record per user
Aside: Never use reserved words as identifiers.
Return the max date from user event grouping by user id. Take that result set and join it back to user event by the user id and max date and filter for just the played records.
Here it is:
First i get the MAX ID from each user and join it to the ROW with this ID
to test if the status are 'played' if so, i get the username of them.
SELECT
ids.*,
u.name,
ue.*
FROM (
SELECt max(id) AS id from UserEvent
GROUP by user_id
) as ids
LEFT JOIN UserEvent ue ON ue.id = ids.id
LEFT JOIN User u ON u.id = ue.user_id
WHERE ue.name = 'played';

How can I return top 4 results by user using Postgres sql

Here is my problem: I have a table that stores the results of surveys taken by users. A single user can take multiple surveys. The key columns are: user_id, the user identifier and survey_id, the unique identifier of the survey. survey_id is incremented each time a survey is taken so if I query a specific user_id, order by survey_id descending and limit to top 4 rows I can get the last 4 surveys for a given user. My problem is I would like to query the last 4 surveys for all users in the table. I'm stumped on how to do this but this is what I have so far:
SELECT *
FROM
(
SELECT user_id
FROM
(
SELECT
user_id, count(all_survey_res_id) as numsurveys
FROM
all_survey_res
GROUP BY user_id
ORDER BY count(all_survey_res_id) DESC
) AS T1
WHERE numsurveys >= 4
)
ORDER BY user_id, all_survey_res_id
This gives me all of the records for each user that has more than 4 surveys but I then want to limit the result to just those top 4 surveys. I could solve this with code back in the application but I would rather see if I can just get the query to do this.
I think you can do this with window functions:
select
*
from (
select
user_id,
survey_id,
row_number() over (partition by user_id order by survey_id desc) rn
from
all_survey_res
) x
where
x.rn <= 4

SQL - Order by the numbers of rows?

So I have a table with 5 columns: id, user_id, news_id, comment and date. Every time a user posts something on the news's comment area the data is inserted into this table.
Now I am trying to make a top poster function that will display the people with the mosts comments posted.
I would like to know how to order the result from this table based on how many times that user_id is present in the table.
For example:
1 - 134(user_id) -> 20 posts(that's how many times this user_id was found in the table.)
2 - 123 -> 19
3 - 168 -> 15
and so on.
Thanks in advance.
SELECT user_id, COUNT (*) as comments
FROM table
GROUP BY user_id
ORDER BY comments DESC
TSQL
select userID, count(*)
from userIDtable
group by userID
order by count(*) desc, userID asc
I think you are confusing rows with columns, but never mind. This is easy to do:
SELECT
user_id,
COUNT(*) posts
FROM
comments
GROUP BY
user_id
ORDER BY
posts DESC
SELECT count(user_id) C, user_id FROM RECORDS ORDER BY C LIMIT 5
"So I have a table with 5 rows: id, user_id, news_id, comment and date. Every time a user posts something on the news's comment area the data is inserted into this table. "
In this answer I'll assume you have meant 5 columns above.
select user_id, count(*) num from tableName group by user_id order by num desc;