I have 2 column (column1 and column2) and I want to select all rows ordered by these 2 columns combined (added together, column1 + column2). Both columns are int values.
How would I do something like this:
SELECT column1, column2 FROM table ORDER BY column1 + column2 DESC;
Example:
----------------------------
| ID | Column 1 | Column 2 |
----------------------------
| 1 | 70 | 20 |
----------------------------
| 2 | 10 | 40 |
----------------------------
| 3 | 30 | 50 |
----------------------------
Ordered output:
Row #1
Row #3
Row #2
You've already got it right. Here is a sqlfiddle that shows it in action.
I've added a second way of querying the table to make it more obvious that the results are returned in the correct order. For this simple example it isn't needed but it's a good way to "debug" your queries, add calculated values to the select portion and initially skip the order by to eliminate errors.
select id, one, two, one + two as sum from ints order by one + two desc;
select id, one, two, one + two as sum from ints order by sum desc;
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 have a table:
id | created
1 | 1563220108
2 | 1563220408
3 | 1563220608
4 | 1563220808
5 | 1563220908
I want to find the lowest ID, where the difference between the current row and the other row is more than 5 minutes.
If you look at my sample data, the difs are as follows:
id | created | dif
1 | 1563220108 | null
2 | 1563220408 | 300
3 | 1563220608 | 500
4 | 1563220808 | 700
5 | 1563220908 | 800
5 x 60 = 300. So, in this case, I would like 2 to be returned.
If id = 2, was instead 301 seconds apart, then it would need to return id = 3.
I am struggling to get my brain to figure out how to write a query that looks at row 1, then row X + 1, then row X + 2 etc. It's not directly comparing the NEXT row. It must compare the first row with the next row, then the first row with the 3rd row, then first row with the 4th row and so forth. Is this even possible with mysql?
UPDATE
Version: 10.1.36-MariaDB
UPDATE 2
I have a database that stores points every couple of seconds. I am trying to write a script that deletes any points that are less than 5 minutes apart. The goal is to decrease the total size of the database, because I don't need to store so many points. I only need points once every 15 minutes or so.
So to do this, I need a script that can find the first id in the table, where the difference between this id and another following row, is bigger than 5 minutes. SO I take it back. It needs to not compare X + 2 and X + 3. It must ALWAYS just compare it with the next value!
So I need a table like this:
id | created | dif
1 | 1563220108 | null
2 | 1563220408 | 300
3 | 1563220608 | 200
4 | 1563220808 | 200
5 | 1563220908 | 100
From this, I should be able to do what I need to do. Going to fiddle and see if I can get this myself.
If the table is named time_data
SELECT AA.id, MIN(BB.id)
FROM time_data AA
INNER JOIN time_data BB
ON TIMESTAMPDIFF(MINUTE, AA.created, BB.created) > 5
GROUP BY AA.id
You can use a correlated subquery and ordering:
select t.*
from t
where not exists (select 1
from t t2
where t2.created < t.created and
t2.created >= t.created - 5 * 60
)
order by t.id asc
limit 1;
I have a MySQL table like below:
| ID | userIDs
---------------
| 1 | 4,3,5
| 2 | 2,3
| 3 | 1,2,3
I want to retrieve all the rows in which userIDs doesn't contain 1.
I tried
SELECT * FROM tablename WHERE 1 NOT IN (userIDs)
But it's not working.
Use FIND_IN_SET
SELECT * FROM tablename
WHERE find_in_set(1, userIDs) = 0
But actually you should rather change your table design. Never store multiple values in a single column!
Suppose there is a table as
| id | value |
| 1 | xyz |
| 4 | abc |
| 5 | test |
I want to select N rows where id is smaller than a number X, but if this result set is less than N rows, I want following rows added to ensure there are N rows selected (unless there is no sufficient rows in this table).
For example, I want to get N=2 rows where id is no larger than X=4, so I get 1st and 2nd rows. But If I want to get N=3 rows for X=4, I want all the three rows.
Can I do this in one statement and try to be efficient?
You want to prioritize the rows. You can do this using order by and limit. Here is an example:
select t.*
from table t
order by (x <= #X) desc, x
limit 2;
I'm currently working with a database table that is structured as follows:
______________________________
| id | content | next_id |
|------|-----------|-----------|
| 1 | (value) | 4 |
| 2 | (value) | 1 |
| 3 | (value) | (NULL) |
| 4 | (value) | 3 |
¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
The value of the next_id field defines the id of the row of data that should follow it. A value of NULL means that no row follows it.
Is there a way I can query the database in such a way that in the resulting rows will be ordered using this method? For example, in the case I gave above, the rows should be returned ordered so that the ids are in this order: 2, 1, 4, 3. I'm looking for a solution that can do this regardless of the number of rows in this sequence.
I know that it is possible to reorder the results after retrieving them from the database (using the programming language I'm working with), but I'm hoping that there is a way that I can do it in SQL.
I can't see a solution without as many self-joins as you have rows. Instead I would build a nested set out of it in a temp table using push down stack algorithm and then retrieve a full tree.
I've got something that's close.
/*one select to init the #next variable to the first row*/
select #next:= id from table1 order by isnull(next_id) asc, next_id asc limit 1;
select distinct a.id, a.next_id from table1 b
inner join
(
select #rank:= id as id, #next:= next_id as next_id from table1
where id = #next
) a
on (b.id = b.id);
This outputs
+----+---------+
| id | next_id |
+----+---------+
| 2 | 1 |
| 1 | 4 |
And then stops. If only I could find a way for it to continue....
Anyway this sort of force feeding values into a query is dodgy enough when doing ranking, let alone this sort of stuff, so maybe I'm going down a dead end.