I extract a number of rows from my DB with a query. Let's say that the result is 120 rows. I want to order these rows by 'score'. That's easy, since every row has a field called 'score'. Next I want to order the first 20 rows of the result randomly. So: 1st order by score, then order first 20 randomly. How would I do this?
EDIT: to be clear: I want to show ALL 120 rows, just onder the first 20 of them randomly.
Thanks!
Let's suppose you've got all your results in a PHP array $rows, using something like this SQL:
SELECT * from `table_name` order by `score`;
It sounds like you know how to do that bit, so I omit the details. The bit you want is the following:
// Get the first 20 rows
$top_twenty = array_slice($rows, 0, 20)
// Order them randomly
shuffle($top_twenty);
// Put them back into the $rows array, with their new order
$rows = array_replace($rows, $top_twenty);
Have you tried shuffling the associative array obtained in the result of the SQL?
$stmt = $db->query("SELECT * FROM table ORDER BY score LIMIT 20");
$array = $stmt->fetchAll(PDO::FETCH_ASSOC);
shuffle($array);
foreach($array as $item) {
// Do something
}
SET #rowNum=0;
SELECT #rowNum:=#rowNum+1 AS rowSeq,t.*
FROM tableName t
ORDER BY case WHEN rowSeq < 20 THEN Rand() ELSE score END
Here is a SQL-only (well MySQL-only) solution:
SELECT *
FROM (SELECT *, #rn := #rn + 1 as rn
FROM table cross join
(select #rn := 0) const
ORDER BY score
) t
ORDER BY (rn <= 20) desc,
(case when rn <= 20 then rand() end),
score;
Related
I want to retrieve all rows from a table starting from the n'th row.
For example, if the table has 20 rows and n=9, I want to retrieve all elements Where the first part of the retrieved elements are the elements from 9 to 20 and the second part are form 1 to 8.
[9,10,...,19,20,1,2,...,7,8].
At first,I thought that I can use 2 queries to do that using LIMIT and OFFSET .
//retrieve the 2nd group
SELECT * FROM Tname WHERE 1 LIMIT (Tsize-n+1) OFFSET (n)
//retrieve the 1st group
SELECT * FROM Tname WHERE 1 LIMIT (n-1)
Where I calculate Tsize-n+1, n and n-1 before, and after retrieving elements I combine the two arrays.
But I don't think that this is the optimal solution (I don't want to use more than one query. and calculating the number of elements in the table is consuming).
Is there a better way to do that?
I have a simple idea. Just select all rows, then read first n rows and finally read remaining rows to the end. Just that!
You can also try this :
(SELECT * FROM Tname WHERE id >= n)
UNION (SELECT * FROM Tname WHERE id < n)
You can use small trick to do this:
SELECT * FROM Tname ORDER BY id >= n DESC, id ASC
This way you have results in that order [9,10,...,19,20,1,2,...,7,8].
If that didn't work (you don't know what id must be used as boundary) you can rearrange results in PHP:
$n = 9;
$resultsArray = array_merge(
array_slice($resultsArray, $n),
array_slice($resultsArray, 0, $n)
);
just reverse order by any column and pass the offset and limit
$data = SELECT * FROM table;
in php
krsort($data);
$chunked_data = array_chunk($data,9);
i have a MySql table that consists of 2 basic things:
The id and a value.
To show that on my page, i need to select, for example, the last 100 rows on reversed order.
So imagine that someone is putting data on it:
Id, value
1, 10
2, 9
3, 21
4, 15
i need, to select the last "3" rows (LIMIT + ORDER Clause), but not like this: 4,3,2 but like this: 2,3,4.
I know how to do that on code, but maybe there is a simple solution for that on Mysql and i don`t know.
Thanks
My SQL Query is like this right now:
SELECT `Data`.`id`, `Data`.`log_id`, `Data`.`value`, `Data`.`created` FROM `control_panel`.`datas` AS `Data` WHERE `Data`.`id` > 1000 AND `Data`.`log_id` = (2) ORDER BY `Data`.`id` DESC LIMIT 100
You need to wrap the first ORDER BY in a subselect which will return a limited selection ordered in descending order, then you can order that result in the outer query in ascending order:
SELECT
a.*
FROM
(
SELECT id, value
FROM tbl
ORDER BY id DESC
LIMIT 3
) a
ORDER BY
a.id
One way to do this would be with a sub-select.
SELECT *
FROM (SELECT * FROM table_name ORDER BY id DESC LIMIT 3) tmp
ORDER BY id ASC
simply
SELECT t.*
(SELECT * FROM table_name
ORDER BY column_name DESC
LIMIT 0,3) t
ORDER BY t.column_name ASC
use DESC to descending order, ASC to increasing order
with this code I select the first 30 row of the table:
SELECT * FROM `table` LIMIT 0 , 30
But how to select the last 30, without changing the order?
It looks like everyone is missing this part:
But how to select the last 30, without changing the order?
First of all, clearly there is no order in the query provided. Assuming the order is ascending on some field this would be the query #DannyFox meant:
SELECT * FROM T
ORDER BY val
LIMIT 0 , 30
Now imagine we have simplified data, such as a, b, c, d, e and that we want only 3 rows instead of 30:
SELECT * FROM T
ORDER BY val
LIMIT 3
If this returns: a, b, c, d, e in each row, then he would expect to get c, d, e in that order. The query everyone is providing:
SELECT * FROM T
ORDER BY val desc
LIMIT 3
Would return e, d, c. The problem with this is that it's actually changing the original order, and the OP say he didn't want to change the order. So technically, the query that would result in c, d, e is:
select * from (
select * from t
order by val desc
limit 3
) s
order by val
Which actually changes the order twice, getting the original order back.
Since you are trying to avoid ordering, then the solution would be to apply it twice.
SELECT *
FROM (
SELECT *
FROM `table_name`
ORDER BY `column_name` DESC -- maybe id?
LIMIT 0, 30
) `table_aliase`
ORDER BY `column_name` ASC
First you need to specify an order:
SELECT * FROM table
ORDER BY some_id ASC -- ascending order
LIMIT 30
If that query returns the first 30 columns, this one will return the last 30:
SELECT * FROM table
ORDER BY some_id DESC -- descending order
LIMIT 30
If you have an auto incremental key/column, say id then here's an example
SELECT * FROM `table` ORDER BY id DESC LIMIT 0 , 30;
Maybe this will work: select * from table WHERE id > ((SELECT MAX(id) from table) - 30);
Nothing is said about an order, so you can not use ORDER BY.
There is a way to get records from a given point, but for that you need to know how many records there are, then use this counted value to provide the limits
SELECT COUNT(*) AS counted FROM table
SELECT * FROM table LIMIT (counted-30),30
Here's my method used with PHP:
$query = "SELECT * FROM table ORDER BY id DESC LIMIT 3";
$res = mysql_query($query);
$results = array();
while($row = mysql_fetch_assoc($res)){
$results = $row[field];
}
// Back to original order based from DB
$results = array_reverse(results);
I have a mysql table. It has auto increment on the id. but I regularly delete rows so the numbers are all over the place. I need to get the last n rows out, but because of deletions, the common way of using the max of the autoincremented id column doesn't work well...
1 - Is their another way to get the bottom 50?
2 - Is their a way to get rows by actual row number? so if I have 4 rows labelled 1,2,3,4 delete row 2 then it will become 1,2,3 rather than 1,3,4?
SELECT ... ORDER BY id DESC LIMIT 50
SELECT *
FROM TABLE
ORDER BY id DESC
LIMIT 50
EDIT
To pick the last 50, but sort by id ASC
SELECT X.*
FROM ( SELECT *
FROM TABLE
ORDER BY id DESC
LIMIT 50
) X
ORDER BY X.id
1 - First get total row count like
SELECT COUNT(*) AS c FROM ...
then use
SELECT ..... LIMIT [start],[count]
2 - One idea is to use view , or procedure, but this is much more harder and may be used when there is no other way to avoid this
1 - Is their another way to get the bottom 50?
SELECT * FROM table_name ORDER BY record_id DESC LIMIT 50
2 - Is their a way to get rows by actual row number? so if I have 4 rows labelled 1,2,3,4 delete row 2 then it will become 1,2,3 rather than 1,3,4?
SELECT * FROM table_name
1 - Yes but it is ugly afaik, you do a
SELECT whateveryouwant FROM table ORDER BY yourprimarykey DESC LIMIT 50
the you fetch the rows into an array and reverse the array, in php :
$r = mysql_query('SELECT * FROM table ORDER BY primarykey DESC LIMIT 50');
$set = array();
while($row = mysql_fetch_assoc($r)) $set = $row;
$set = array_reverse($set);
foreach($set as $row) {
// display row ...
}
2 - You'll have to manage your primary key by yourself, its a bit risky ...
I want to do this:
Check the top 10 values of points.
Here is my condition:
If there are less than 10 records (rows) found, e.g give bonus
If the points is in top ten (among hundreds records/rows), give bonus.
So, what i do is (wrong method):
SELECT points FROM `scores` WHERE id = '1' ORDER BY score DESC LIMIT 9 , 1
That will only work if i have more then 9 (at least 10) data/records.
Is there any other way?
I am thinking of using this(not very good though):
SELECT points FROM `scores` WHERE id = '1' ORDER BY score DESC LIMIT 0 , 10
Then get the last value of mysql_fetch_assoc data. Thus, how do I get the last value of mysql_fetch_assoc data?
The previous query is close to what you want:
SELECT points FROM (
SELECT points, score
FROM scores
WHERE id = '1'
ORDER BY score DESC
LIMIT 10
) AS top_ten
ORDER BY score ASC
LIMIT 1
If you want to stick with mysql_fetch_assoc getting the last value you can utilize mysql_data_seek.
Something like this:
<?php
// ... $result is the result set from your query
$result_count = mysql_num_rows($result);
if ($result_count > 0)
{
mysql_data_seek($result, $result_count - 1);
}
$row = mysql_fetch_assoc($result);
?>
try to use this:SELECT points FROM (SELECT points FROM scores WHERE id = '1' ORDER BY score DESC LIMIT 10) ORDER BY score LIMIT 1