My table is of the form below
| ID | TIME | USER | DATA|
| 1 | 1542785267683 | A | hi |
| 2 | 1542785385809 | B | hello |
| 3 | 1542785385809 | C | hey |
| 4 | 1542785385809 | D | hii |
| 5 | 1542785385809 | E | hola |
| 6 | 1542795485058 | F | hiiiii |
The table will be in same form as above with 1000s of rows. I want to retrieve the latest 3 rows and then the next 3 rows from the table to display the rows to the user, same as you view messages when you swipe upwards in messaging apps.
I tried the following methods:
Retrieval based on time of the last message of first selected chunk. But it is not possible since two or more rows could be in same time and this will result in displaying the same row twice.
SELECT * FROM MessageM WHERE TIME_RECEIVED < NOW() ORDER BY TIME_RECEIVED DESC LIMIT 3;
SELECT * FROM MessageM WHERE TIME_RECEIVED < 1542785385809 ORDER BY TIME_RECEIVED DESC LIMIT 3; # Leaves two row
SELECT * FROM MessageM WHERE TIME_RECEIVED <= 1542785385809 ORDER BY TIME_RECEIVED DESC LIMIT 3; # duplicates two row
I read the answer mentioned below
MySQL : retrieve a large select by chunks
My requirement is almost the same except the table could be updated in between the time to chunks were retrieved.
So When using the following queries
SELECT * FROM Message ORDER BY TIME DESC LIMIT 0, 2;
SELECT * FROM Message ORDER BY TIME DESC LIMIT 2, 4;
If a new row is inserted between the consecutive selects the same row already displayed will again be obtained for the next select statement. Locking is not at all possible.
Could auto increment column solve the problem or Any other methods like adding new column with some other constraint solve the problem or some form of partition.
I have planned on using the following query
SELECT * FROM Message WHERE TIME <= 1542785385809 AND ID NOT IN (5, 4) ORDER BY TIME DESC LIMIT 3;
Get the time of the last row and get the ids of all rows with the given time from the retrieved rows. When querying for the second time enter the ids in NOT IN condition.
Is there any other better way to do it. Could auto increment column solve the problem or Any other methods like adding new column with some other constraint or some form of partition.
First, do not use time column to sort - use ID instead. I suppose your ID column is an auto-increment integer, so it's unique and time-of-insert sorted.
Second, let's consider an approach used by social networks (for example LinkedIn): you load the feed (latest N rows). When you scroll to the bottom of the page next rows are loaded (another N rows). When new posts become available, you push "New posts" button which resets current view completely and goes to the beginning. This takes you back to step 1, efficiently loading latest N rows.
Technically, this is done this way:
SELECT * FROM MessageM ORDER BY ID DESC LIMIT 3;
Returning:
| 6 | 1542795485058 | F | hiiiii |
| 5 | 1542785385809 | E | hola |
| 4 | 1542785385809 | D | hii |
You remember ID=4 as the last seen post. For the next page you load:
SELECT * FROM MessageM WHERE ID < 4 ORDER BY ID DESC LIMIT 3;
Returning:
| 3 | 1542785385809 | C | hey |
| 2 | 1542785385809 | B | hello |
| 1 | 1542785267683 | A | hi |
You remember ID=1 as the last seen post. For the next page you load:
SELECT * FROM MessageM WHERE ID < 1 ORDER BY ID DESC LIMIT 3;
Returning no rows. This means you can not load any older posts.
To reset everything you just go to step 1:
SELECT * FROM MessageM ORDER BY ID DESC LIMIT 3;
Returning:
| 7 | 1542785385809 | A | some new post |
| 6 | 1542795485058 | F | hiiiii |
| 5 | 1542785385809 | E | hola |
So you read the new post and you also have more pages now.
Related
I have a table that looks like below:
| id | group_id | title |
-------------------------
| 1 | 1 | Hello |
| 2 | 1 | World |
| 3 | 2 | Foo |
| 4 | 2 | Bar |
My query may look like below to return the results above:
SELECT * FROM my_table ORDER BY id
Question
How can I order this table so that the group ids appears to be random, but still the same every time the query is executed.
Possible result example
This result looks to be in a random order. If I run the same query a week later, I want to see the exact same order which means it's not really random.
| id | group_id | title |
-------------------------
| 2 | 1 | World |
| 4 | 2 | Bar |
| 1 | 1 | Hello |
| 3 | 2 | Foo |
Appears to be random from a group_id perspective. It's no longer ordered by group_id like 1 1 2 2, but 1 2 1 2. It could also have been 2 1 1 2 or something that does not increase.
Should return the same results every time, not random each time.
I could order by title but if a title should change that row will be reordered. So the order needs to be made with the id I guess.
I want to avoid file or database caching if possible.
Is it possible?
How about taking the modulo function for your advantage.
SELECT * FROM my_table ORDER BY id % 3,id
Define a value to use with the modulo function (in my example 3) and order your table by the modulo of the id.
This should return the same order everytime you run the query and return some order that is pseudo random.
Since the modulo function can return the same value for different ids you also need to order by the original id to have a defined, reproducable order.
order this table so that the group ids appears to be random
Only ORDER BY RAND() may provide really random ordering.
but still the same every time the query is executed
Create separate static ordering table, fill it randomly with source table's ids, join it and order by it.
I did not solve the problem with the solution from #Kylro, but I found another way which works great.
SELECT * FROM my_table ORDER BY COS(id), id
Cos is sometimes a positive value and sometimes a negative value, almost random like. It works perfecty for this problem.
I want to make a selection in my MySQL database where I have stored numerical values in a specific column.
I have seen some websites that show 10 ten based on some criteria, and I've been wondering if it will be possible to make a selection based on numerical values.
I have my database like so:
| id | name | pts |
+----+-----------+-----+
| 1 | Brad | 3 |
| 2 | Jane | 8 |
| 3 | Jones | 10 |
| 4 | Paty | 15 |
| 5 | Sammy | 2 |
Now my question is, how do I make a query that selects only the top 3 users, based on the pts, such that it returns the result as:
1st Position = Paty => 15pts
2nd Position = Jones => 10pts
3rd Position = Jane => 8pts
?
try this :
SELECT * FROM tablename ORDER BY pts desc limit 3
Your query should use LIMIT to get the top results:
SELECT id, name, points FROM table ORDER BY pts DESC LIMIT 3
shoul do the trick.
Order by will order the table from the highest to the lowest and limit will tell mysql to get only the first three results
You can find more on this topic here for example.
And this is a question very close to your
you can use this query
SELECT CONCAT(`id` , 'Postion = ' , `name` , '=>' ,`pts` , 'pts' ) AS result FROM table ORDER BY pts DESC LIMIT 3
This Question I seen many places anyway the query is.
select top 3 * from tablename order by cols_name desc
This Query brings top 3 row with highest values based on your column.
I'm trying to get and display an order list including the current status.
#orders = Order.joins(order_status_details: :order_status)
.order('id DESC, order_status_details.created_at DESC')
.select("orders.id, order_status_details.status_id, order_statuses.name, order_status_details.created_at")
It works good but is returning all the rows with order ids duplicated like this:
+----+-----------+----------------------+---------------------+
| id | status_id | name | created_at |
+----+-----------+----------------------+---------------------+
| 8 | 1 | Pending | 2016-01-31 16:33:30 |
| 7 | 3 | Shipped | 2016-02-01 05:01:21 |
| 7 | 2 | Pending for shipping | 2016-01-31 05:01:21 |
| 7 | 1 | Pending | 2016-01-31 04:01:21 |
+----+-----------+----------------------+---------------------+
The correct answer must return uniques ids, for the example above should be the first and second row.
I was already trying with distinct on select, .distinct, .uniq and .group but I'm getting an error.
Thanks.
First of all, I believe your model is "An Order has many OrderStatusDetail". So that is the reason why you have several different name in your result.
So you can modify the query like this:
#orders = Order.joins(order_status_details: :order_status)
.order('id DESC, order_status_details.created_at DESC')
.where('order_status_details.id IN (SELECT MAX(id) FROM order_status_details GROUP BY order_id)')
.select("orders.id, order_status_details.status_id, order_statuses.name, order_status_details.created_at")
Ideally, the where condition is used for selecting just the expected id of order_status_details, I use min_id for example, you can modify it as needed
I my mysql db I have a table with 3 parameters ( name, views, id ). I need to get row ordered by views. I'm getting something like this.
query:
select
from table
order by views
Result:
id | name | views
------------------------
7 | xxxx | 9000
2 | yyyy | 8000
1 | aaaa | 7000
4 | bbbb | 6000
8 | dddd | 5000
6 | cccc | 4000
5 | oooo | 3000
3 | tttt | 2000
What I need to do, is to get rows ordered by views but starting with specyfic ID. Is it possible. All input that i have is ID. Let sat that ID is 6, this should be output:
id | name | views
------------------------
6 | cccc | 4000
5 | oooo | 3000
3 | tttt | 2000
I can't use LIMIT as I don't really know what is possition at the moment. I just need to get rows which are left starting with ID.
What I'm trying to do is to get infinite scroll, I requesting next elements base on last element that was displayed. Only tricky part is that I'm ordering by views parameter.
select * from table
where (views = 4000 and id>6) or (views < 4000)
order by views desc, id asc;
The tricky part is that you have to know (select) the views of the element with ID 6; also you need to use the ID as secondary sort criteria in order to get consistent results.
Actually this is a common case of a since,until type of paging
SELECT * FROM table
WHERE views <= (SELECT views FROM table WHERE id = 6)
ORDER BY views
I need to fetch a repeatable random set of rows from a table using MySQL. I implemented this using the MySQL RAND function using the bigint primary key of the row as the seed. Interestingly this produces numbers that don't look random at all. Can anyone tell me whats going on here and how to get it to work properly?
select id from foo where rand(id) < 0.05 order by id desc limit 100
In one example out of 600 rows not a single one was returned. I change the select to include "id, rand(id)" and get rid of the rand clause in the where this is what I got:
| 163345 | 0.315191733944408 |
| 163343 | 0.814825518815616 |
| 163337 | 0.313726862253367 |
| 163334 | 0.563177533972242 |
| 163333 | 0.312994424545201 |
| 163329 | 0.312261986837035 |
| 163327 | 0.811895771708242 |
| 163322 | 0.560980224573035 |
| 163321 | 0.310797115145994 |
| 163319 | 0.810430896291911 |
| 163318 | 0.560247786864869 |
| 163317 | 0.310064677437828 |
Look how many 0.31xxx lines there are. Not at all random.
PS: I know this is slow but in my app the where clause limits the number of rows to a few 1000.
Use the same seed for all the rows to do that, like:
select id from foo where rand(42) < 0.05 order by id desc limit 100
See the rand() docs for why it works that way. Change the seed if you want another set of values.
Multiply the decimal number returned by id:
select id from foo where rand() * id < 5 order by id desc limit 100