SQL Trending Data - mysql

I am trying to create a Trending Posts database call for my homepage.
The best way I thought of doing this, would be by making 2 integer tables.
The problem I am having, is sorting these results.
Here is what my table looks like, I keep track of the last 10 trending posts.
name trending clicks
post1 10 5
post2 9 15
post3 8 12
post4 7 10
post5 6 8
post6 5 8
post7 4 22
post8 3 18
post9 2 8
post10 1 8
The Trending Position is updated every 4 hours and clicks are reset to 0.
From this data, I need to pull the posts in this order
name trending clicks
post6 5 22
post8 3 18
post2 9 15
post3 8 12
post4 7 10
post5 6 8
post9 2 8
post10 1 8
post1 10 5
Here is another example:
name trending clicks
post1 10 0
post5 6 9
post2 9 0
post3 8 0
post4 7 0
post6 5 0
post7 4 0
post10 1 3
post8 3 0
post9 2 0
I need to sort these results, based on the clicks ONLY if they are above the trending position.
Example: If post #8 get's more clicks than position #4, it will take it's spot and keep the order of the trending, but use the clicks to also order the data.
The original posts will keep their position until a trending post has gotten more clicks than the position to take it's place.
The problem i'm trying to resolve, is when I reset the trending data. I reset the data every 4 hours but want to keep the positions and weight on each trending post.
Did I explain this well enough and can anybody please help me?

Why this doesnt work for you ?
SELECT name, trending, clicks
FROM YourTable
ORDER BY clicks DESC
But if you want keep previous trend, then you need add a weight column.
SELECT name, trending, clicks, weight
FROM YourTable
ORDER BY ((clicks + weight) /2) DESC
Instead of reset your trend every 4h wouldnt be easy calculate the clicks on the last 4h. You have to record datatime for each click
SELECT name, count(clicks) as clicks
FROM YourTable
WHERE datetime > DATEADD(h,-4,GETDATE())
GROUP BY name
ORDER BY count(clicks) DESC

Related

Getting messages within 5 minutes from a specific ID and timestamp MYSQL

I'm building a chat app retrieving chat history when a certain chat is expanded but i want a function or functions that can help me get chats that are 5 minutes within each other and are sent by the same user let's say given this table below
id
message
msg_owner_id
msg_reciever
msg_time
msg_type
seen
seen_time
note(not part of table)
1
hey
20
6
10:42:51
interchats
0
<----- 20 sent to 6
2
hi
20
6
10:43:20
interchats
0
<------20 sent to 20
3
am fine
20
6
10:44:11
interchats
0
<------20 sends to 6 again
4
mannnn
6
20
10:45:02
interchats
0
<-- 6 replies to 20
5
mannnn
20
11
10:53:02
interchats
0
<-- 20 sends to 11
I have used the following code however some values are missing
SELECT GROUP_CONCAT(id), DATE_FORMAT(msg_time, '%Y-%m-%d %H:%i'),
id as ID, msg_owner_id as MSG_OWNER, msg_reciever as MSG_RECEIVER,
message as MESSAGE
FROM chats WHERE msg_time >= :msg_time - INTERVAL 5 MINUTE AND id >= :id
GROUP BY 2 ORDER BY 2
let's say we need to start from id 1 and timestamp 10:42:51, how do I select all the chats sent within a 5 minutes interval from ID 1 and timestamp 10:42:52
Desired result should be:
the following IDs returned 1, 2 and 3

Limit selected results by unique selected IDs when using left joins

I have a table users and some other tables like images and products
Table users:
user_id user_name
1 andrew
2 lutz
3 sophie
4 michael
5 peter
6 oscor
7 anton
8 billy
9 henry
10 jon
Tables images:
user_id img_type img_url
1 0 url1
1 1 url4
2 0 url5
7 0 url7
8 0 url8
9 1 url9
Table Products
user_id prod_id
1 5
1 55
2 555
8 5555
9 5
9 55
I use this kind of SELECT:
SELECT * FROM
(SELECT user.user_id,user.user_name, img.img_type, prod.prod_id FROM
users
LEFT JOIN images img ON img.user_id = users.user_id
LEFT JOIN products prod ON prod.user_id = users.user_id
WHERE user.user_id <= 5) AS users
ORDER BY user.user_id ASC
The result should be the following output. Due to performance improvements, I use ORDER BY and an inner select. If I put a LIMIT 5 within the inner or outer select, things won't work. MySQL will hard LIMIT the results to 5. However I need the LIMIT of 5 (pagination) found unique user_id results which would lead to 9 in this case.
Can I use maybe an if-statement to push an array with found user_id and break/finish up the select when the array consist of 5 UIDs? Or can I modify somehow the select?
user_id user_name img_type prod_id
1 andrew 0 5
1 andrew 1 5
1 andrew 0 55
1 andrew 1 55
2 lutz 0 5
2 lutz 0 55
3 sophie null null
4 michael null null
5 peter null null
results: 9
LIMIT 5 and user_id <= 5 do not necessarily give you the same results. One reason: There are multiple rows (after the JOINs) for user_id = 1. This is because there can be multiple images and/or multiple products for a given 'user'.
So, first decide which you want.
LIMIT without ORDER BY gives you an arbitrary set of rows. (Yeah, it is somewhat predictable, but you should not depend on it.)
ORDER BY + LIMIT usually implies gathering all the potentially relevant rows, sorting them, then doing the "limit". There are sometimes ways around this sluggishness.
LEFT leads to the NULLs you got; did you want that?
What do you want pagination to do if you are displaying 5 items per page, but user 1 has 6 images? You need to think about this edge case before we can help you with a solution. Maybe you want all of user 1 on a page, even if it exceeds 5? Maybe you want to break in the middle of '1'; but then we need an unambiguous way to know where to continue from for the next page.
Probably any viable solution will not use nested SELECTs. As you are finding out, it leads to "errors". Think of it this way: First find all the rows you need to display on all the pages, then carve out 5 for the current page.
Here are some more musings on pagination: http://mysql.rjweb.org/doc.php/pagination

Sort values in two column and insert order position into another column in mysql

I have a database about sports event that contains:
*User ID
*Amount of Points that the user got on that event
*Time (HH:MM:SS) that took the user to complete track.
How can I first sort them by no. of points, then if two users have same amount of points, by time (shorter is better); and then insert the places to rows?
I have database like that:
ID No. of Points Time Place
------------------------------------
1 15 00:56:00
2 13 00:55:15
3 17 01:00:00
4 17 00:57:00
5 19 00:52:15
I need to have it with places:
ID No. of Points Time Place
------------------------------------
1 15 00:56:00 4
2 13 00:55:15 5
3 17 01:00:00 3
4 17 00:57:00 2
5 19 00:52:15 1
I hope, you understand that. Sorry for bad English.
Best regards,
You can do this with update statement as follows.
SET #placeValue:=0;
UPDATE [Table Name] SET Place=#placeValue:=#placeValue+1 ORDER BY
[Amount of Points] DESC,Time ASC

Add together grouped rows into one value

I've got an issue where I've been presented data in this format from SQL, and have directly imported that into SSRS 2008.
I do have access to the stored procedure for this report, however I don't want to change it as a few other reports rely on it.
Project HoursSpent Cost
1 5 45
1 8 10
1 7 25
1 5 25
2 1 15
2 3 10
2 5 15
2 6 10
3 6 10
3 4 5
3 4 10
3 2 5
I've been struggling all morning to understand how/when I should be implementing the SUM() function with this.
I have tried already to SUM() the rows, but it still outputs the above result.
Should I be adding any extra groups?
Ideally, I need to have the following output:
Project HoursSpent Cost
1 25 105
2 15 40
3 16 30
EDIT: Here is my current structure:
"LineName" is a group for each project
You have to add a row group on "Project" since you want to sum up the data per each project.

mysql query to get charges

I have the table below
relID value charge
1 2 5
1 8 2
2 1 10
2 4 6
2 9 2
For the above table i need for a given value ex 10 to find what to charge for each relID
In the above for value<10 i need to get charge=5 for relID=1 and charge=2 for relID=2
I am trying to use 1 sql command to get it and i am kind of lost
Can anyony help
Thanks
Your question isn't very clear but I think this will work for you
SELECT t.relID,
(
SELECT charge
FROM table
WHERE relID = t.relID
AND value < 10
ORDER BY value
LIMIT 1
) AS charge
FROM table AS t
Let me rephrase.
Here is the table
relID value charge
1 2 5
1 8 2
2 1 10
2 4 6
2 9 2
Explain the table :
Lets say that the value and charge are money.
If the user has value 2 then i must charge with 5 using relID 1
If the user has value 8 then i must charge with 2 using relID 1
same for the relID 2
So when a user come with a value 10 i must find what to charge.So for the given value 10 i must find in the table all records with value<10.
In the example the values for value <10 are
For relID=1 are (2,8)
For relID=2 are (1,4,9)
Now for each relID i need to get the max value.
For relID=1 max value is 8 so charge is 2
For relID=2 max value is 9 so charge is 2
I plain english there are value rate
0-2 charge 5
2-8 charge 2
and ...
i hope to be clear now
select *
from Table t
where value =
(select max(value)
from Table
where value <= 10
and relId = t.relId)