SQL multiple column ordering randomly - mysql

I want to order highlight by rand() without modifying the syntax. How to do ?
I've tried with ORDER BY servers.highlight rand() but still not working.
ORDER BY `servers`.`highlight` DESC, `servers`.`votes` DESC,`servers`.`online_players` DESC,`servers`.`status` DESC

The only way to achieve this is to do the random ordering of servers.highlight in the original JOIN. Attempting to ORDER BY RAND() at the end will simply give random ordering to the entire output. Something like this:
SELECT *
FROM (SELECT * FROM servers.highlight ORDER BY RAND()) h
JOIN servers.votes ON ...
I've created a small demo on dbfiddle to demonstrate.

Related

Obtaining the maximum value with Order By and Limit 1

First of all, I am using MySQL. When I make the following query:
SELECT CodE,sum(tiempo) AS 'tiempo total'
FROM Participa
GROUP BY CodE
ORDER BY 'tiempo total' DESC LIMIT 1;
it shows me the first line of my table instead of the MAX value. However, If I make the following query:
SELECT CodE,sum(tiempo)
FROM Participa
GROUP BY CodE
ORDER BY 2 DESC LIMIT 1
I get the correct result.
I have just changed the alias 'tiempo total' for somthing that should be equivalent.
How it´s possible?
Only use single quotes for string and date constants -- never for column aliases. So:
SELECT CodE, sum(tiempo) AS `tiempo total`
FROM Participa
GROUP BY CodE
ORDER BY `tiempo total` DESC
LIMIT 1;
You are ordering by a constant string, not the name of a column. Hence, if you get the maximum in your query, it would be a total accident.
Note: You can get around these issues by giving columns names that never need to be escaped:
SELECT CodE, sum(tiempo) AS tiempo_total
FROM Participa
GROUP BY CodE
ORDER BY tiempo_total DESC
LIMIT 1;
Easier to type, too.

Returning a range of rows in MySQL relative to either beginning or end of the result set

I've got a query that is returning a set of rows. I want to LIMIT what actually gets returned to some subset of these rows by range, relative either to the beginning or end of the range. I can do this easily if the range is only relative to the beginning. For instance, if I want to return rows 5-7 I can do:
SELECT * FROM <table> WHERE <condition> ORDER BY rowid ASC LIMIT 5,2
The only translation I need to do is from (index0,index1) to offset,length where offset=index0 and length=index1-index0.
But I also am trying to allow the range to be specified relative to the end of the range in a single query, i.e. without running a query first to determine the number of rows and then a second query based on this information. So for example if I specify a row range of (-5,-1) this means that I want the last five rows returned. I cannot pass a negative value to LIMIT.
In reading similar questions, one proposed solution seemed to be to change the ORDER of the query. So I suppose I could do:
SELECT * FROM <table> WHERE <condition> ORDER BY rowid DESC LIMIT 1,5
Now I have two problems. First, the returned set is in the wrong order, I still want it return in ascending order. So now I have to have a subquery to reorder everything:
SELECT * FROM (SELECT * FROM <table> WHERE <condition> ORDER BY rowid DESC LIMIT 1,5) AS x ORDER BY x.rowid ASC;
I'm not sure if there is a better way to do it than that, but there is a second issue: this does not work if the starting and ending part of the range are mixed as to what they are relative to. Suppose I want to return the range (10,-2) which is all rows from the tenth to the next to last. In this case, neither of the above approaches will work.
I also saw where the function mysql_num_rows() was mentioned although it did not give example SQL of how to use it.
SELECT * FROM <table> WHERE <condition> ORDER BY rowid DESC LIMIT 10,mysql_num_rows()-2;
But when I try to run this query, I get this error:
ERROR 1327 (42000): Undeclared variable: mysql_num_rows
What about reversing your approach? Asking for rows in range (10, -2) means "everything except first nine rows and last one".
You can translate it into
select * from yourTable order by rowid asc
minus
select * fom yourTable order by rowid asc limit 9
minus
select * fom yourTable order by rowid desc limit 1
Edit
Since MySQL does not support MINUS, the query above could be rewritten using left join instead
select t1.*
from yourTable t1
left join
(select rowid fom yourTable order by rowid asc limit 9) t2
on t1.rowid = t2.rowid
left join
(select rowid fom yourTable order by rowid desc limit 1) t3
on t1.rowid = t3.id
where t2.rowid is null and t3.rowid is null
order by t1.rowid asc
This is based on a different answer that was given to this question, which used MINUS. Unfortunately, MySQL does not support this operator. I used NOT IN instead, and furthermore I had to wrap my query inside additional queries to avoid the MySQL issue of lack of support for LIMIT being in an IN sub-query.
So the premise of the solution as provided by the other answer is to treat a positive starting index and a negative ending indexes as a different case from both indicies negative or positive. Then, select everything but exclude the range at the start and finish. The actual code that MySQL likes and which works for the example range of (10,-2) is:
SELECT *
FROM <table>
WHERE <conditions>
AND rowid NOT IN
(
SELECT * FROM (
SELECT rowid FROM <table> WHERE <conditions> ORDER BY rowid ASC LIMIT 9
)
)
AND rowid NOT IN
(
SELECT * FROM (
SELECT rowid FROM <table> WHERE <conditions> ORDER BY rowid DESC LIMIT 1
)
)
Or more generally, for the range (i0,i1) where i0>=0 and i1<0, replace 9 with i0-1 and 1 with -i1-1. Of course, if either of these values are less than one, that portion of the query can be excluded.

How to select words of the same CHAR_LENGTH in MySQL-PHP?

In order to use in a multiple choice test on Chinese Language, I need to select 5 words, all of them must have the same number of characters, one for the question, four for options. What I have been doing is:
SELECT hanzi, CHAR_LENGTH(hanzi) chlen FROM wordlist ORDER BY RAND() LIMIT 1
From here I get chlen to use it in another statement:
SELECT hanzi FROM wordlist WHERE CHAR_LENGTH(hanzi)=$chlen ORDER BY RAND() LIMIT 4
Can I do this using only one statement?
You can use subquery to achieve this:
SELECT hanzi FROM wordlist WHERE CHAR_LENGTH(hanzi) in (SELECT CHAR_LENGTH(hanzi) chlen FROM wordlist ORDER BY RAND() LIMIT 1) ORDER BY RAND() LIMIT 4
I haven't tested it, so it might give some errors; but at least you can get a idea from this.
Try
SELECT * FROM table ORDER BY length(column);
Ref
Documentation on the length() function, as well as all the other string functions, is available here.

SQL First() Function

I am using phpMyAdmin to write some SQL code that I thought was simple but proving to be a headache. I'm using this tutorial to help me out. My goal is to get the first and last columns id's from a result set. When I do this query I get 5 rows starting at 15 and going through 11.
SELECT id
FROM boardPost
WHERE recipientId = 1
ORDER BY id DESC
LIMIT 0,5
However, when I try this query I get an error #1064: "You have an error in your SQL syntax."
SELECT FIRST(id)
FROM boardPost
WHERE recipientId = 1
ORDER BY id DESC
LIMIT 0,5
Something like this maybe?
SELECT min(id), max(id)
from (
select id
from boardPost
where recipientId = 1
order by id desc
limit 0,5
) t
I think that is what you want?
Select id from boardPost order by id asc limit 1
and
Select id from boardPost order by id desc limit 1
If you just want the first and the last id of a result set, you could consider this:
SELECT MIN(id) firstId, MAX(id) lastId FROM someTable WHERE aField = 1;
Note that it'll only work if you do use and ORDER BY an AUTO_INCREMENT field, else you might get unexpected results.
It'll only work with the full set. If you need the first and last id of a limited one, you're probably better of using 2 queries with ASC and DESC order and LIMIT 1.
MySQL does not support the FIRST() function. You will need to use the workaround they specified in that tutorial (using ORDER BY and LIMIT)
In some situations (like mine, that first brought me here), there are some rarely-used MySQL "windowing functions" such as FIRST_VALUE and LAST_VALUE that may provide the functionality you're seeking.
(Here's more info on Window Function Concepts and Syntax, and the Wikipedia description of the term.)

SQL Query using Random

Hi could anyone help me with something?
I need a mysql query that can return 4 values from a column in some table, also select all fiels from each row.
something like:
SELECT * FROM dadoslivros WHERE RAND() =1 limit 100;
But i only want the random form row ID.
Thanks.
It seems like you just want to use ORDER BY RAND():
select *
from dadoslivros
order by rand()
limit 100
See SQL Fiddle with Demo