HiveBrain v1.2.0
Get Started
← Back to all entries
patternsqlMinor

MySQL - Order by closest value on multiple columns

Submitted by: @import:stackexchange-dba··
0
Viewed 0 times
ordercolumnsvaluemysqlmultipleclosest

Problem

I have a table for a game lobby. In this lobby a user gets put in their connection and their level. In my SQL statement I am getting all the users in the lobby which are between +5/-5 of the user's level and connection. However I want to order this so that a user's level is the most important and then it will look at the connection. So if there are two users with the same level, it will look at the connection instead. Maybe there will be more columns in future that can be used to further refine the search. I have seen that on single column selects like this, I could use abs() however I'm not sure if this is possible on this as well?

create table users (
  id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  connection INT(11),
  level INT (11)
);

create table lobby (
  id INT(11) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
  user_id INT(11),
  CONSTRAINT user_id FOREIGN KEY (id)
  REFERENCES users(id)
);

insert into users values (null,5,6);
insert into users values (null,7,10);
insert into users values (null,10,9);
insert into users values (null,10,4);
insert into users values (null,1,8);

insert into lobby values (null,1);
insert into lobby values (null,2);
insert into lobby values (null,3);
insert into lobby values (null,4);
insert into lobby values (null,5);


So if I'm using user_id = 1 as my user I would have the following select statement:

select lobby.id, lobby.user_id, users.connection, users.level
from lobby INNER JOIN users
ON lobby.user_id = users.id 
where user_id <> 1 and 
users.connection between 0 and 10 and
users.level between 1 and 11
order by abs(connection-5);


This select statement comes back with the following table:

| id | user_id | connection | level |
|----|---------|------------|-------|
|  2 |       2 |          7 |    10 |
|  5 |       5 |          1 |     8 |
|  3 |       3 |         10 |     9 |
|  4 |       4 |         10 |     4 |


However what I want is the following output:

```
| id | user_id | connection | level

Solution

Simply add another column,
order by abs(connection-5), abs(level-4) is valid syntax:

select lobby.id, lobby.user_id,
   users.connection, users.level
from lobby INNER JOIN users
ON lobby.user_id = users.id
where lobby.user_id <> 1
  and users.connection between 0 and 10 
  and users.level between 1 and 11
order by abs(connection-5), abs(level-4);

Code Snippets

select lobby.id, lobby.user_id,
   users.connection, users.level
from lobby INNER JOIN users
ON lobby.user_id = users.id
where lobby.user_id <> 1
  and users.connection between 0 and 10 
  and users.level between 1 and 11
order by abs(connection-5), abs(level-4);

Context

StackExchange Database Administrators Q#127090, answer score: 2

Revisions (0)

No revisions yet.