Select row <= value - mysql

So I'm currently using the following bit of SQL to select the closest rank value to the given variable but I'm looking to implement a feature so I can grab the closest rank value but nothing greater than the variable.
Here is my current SQL statement:
SELECT rank, points
FROM `4star`
WHERE arenaID = 6
ORDER BY ABS(rank - $v) ASC
LIMIT 1
$v indicates the PHP variable.
If this was my table:
+---------+----------+
| rank | points |
+---------+----------+
| 1 | 9 |
| 50 | 7 |
| 200 | 6 |
| 5000 | 4 |
| 10000 | 1 |
+---------+----------+
how would I select the closest rank to 3000 that was not greater than 3000? So the row I would get would be 200 => 6?

Try this:
SELECT rank,points
FROM `4star`
WHERE rank <=3000
AND arenaID = 6
ORDER BY rank Desc
LIMIT 1

how would I select the closest rank to 3000 that was not greater than
3000?
Use WHERE to select rows where rank is less than/equal to 3000, then ORDER BY rank descending and LIMIT the results to one row:
SELECT rank
FROM table
WHERE rank <= 3000 AND arenaID = 6
ORDER BY rank DESC
LIMIT 1

Related

How to select last 4 data which start from second last row using sql

I have table named posts with 3 columns which are id, details, date which contains the following data in ascending order:
+----+----------+-------+
| id | details | date |
+----+----------+-------+
| 1 | details1 | date1 |
| 2 | details2 | date2 |
| 3 | details3 | date3 |
| 4 | details4 | date4 |
+----+----------+-------+
I want to select data in descending order but I want to leave the first row details, like I want to leave row 4th id details, details4, date4, but then I want to select data from id 3 to 2 in, like order by id desc limit 2 but leave the first row from last
You can use the query with ORDER BY DESC LIMIT 1, n
That way, n is the amount of rows you want to fetch, and you're skipping the first row of the result by using LIMIT 1, .
WITH a AS (
SELECT 1 i
UNION ALL
SELECT 2 i
UNION ALL
SELECT 3 i
UNION ALL
SELECT 4 i
)
, b as (
SELECT TOP 1 i FROM a ORDER BY i DESC
)
SELECT *
FROM A
EXCEPT
SELECT * FROM B
ORDER BY i DESC

how to sort results by specific values in mysql

We have a DB called transaction. It has user_id, date, value and so on. I use pagination in my query also. I have thousands of record in my table which has user_id equal to 2 or other value. put the user_id = 2 at the very last page.
I want to sort the result like this:
sort the results by date but if the user_id= 2 , put all results associated with the user_id= 2 at the end.
to be more clear, I show you what I want in the below.
-------------------------------------
| ID | user_id | date | ......
-------------------------------------
| 1 | 10 | 2018-10-20 |
-------------------------------------
| 2 | 11 | 2018-10-21 |
-------------------------------------
| 3 | 2 | 2018-10-22 |
-------------------------------------
| 4 | 2 | 2018-10-23 |
the results have to be like this:
first: ID = 2, second: ID = 1, third: ID = 4, last: ID = 3
tip *:
I use field function but unfortunately in vain.
ORDER BY FIELD(user_id, 2) DESC, date DESC
You may try using a CASE expression in your ORDER BY clause:
SELECT *
FROM yourTable
ORDER BY
CASE WHEN user_id = 2 THEN 1 ELSE 0 END,
date DESC;
I'm not sure if you want each group sorted by date ascending or descending. If you want ascending date order, then remove the DESC keyword at the end of my query.

Firstly do Group By then retrieve all rows as per order?

I have table where I have id and time.
ID | Time
1 | 8.35
1 | 8.40
3 | 8.43
4 | 8.45
1 | 8.50
2 | 8.52
3 | 8.54
4 | 8.55
1 | 8.57
2 | 9.01
3 | 9.05
5 | 9.06
Required Result
ID | Time
5 | 9.06
3 | 9.05
3 | 8.54
3 | 8.43
2 | 9.01
2 | 8.52
1 | 8.57
1 | 8.50
1 | 8.40
1 | 8.35
4 | 8.55
4 | 8.45
Currently I am doing it by Select * from table group by ID order by Time DESC and get
Result One:
ID | Time
5 | 9.06
3 | 9.05
2 | 9.01
1 | 8.57
4 | 8.55
then writing second query and storing data in list.
foreach value in Result one:
Select * from Table where ID = value
Instead of writing a loop, I will like to have only one query.
Basic problem is I want to group IDs and top group should be the item that occured recently. As in example 1 occurs many time but I will consider only the latest time while grouping.
Can I write only one query to get result?
SELECT ID, Time FROM Table ORDER BY ID, Time
Grouping combines matching rows, so you do not want to group, ordering puts them in order, and that's what you want, you want all the IDs in order then all the times in order within those ids, so you want to order by ID then order by time.
UPDATE due to question edit
This can be done with a join to a sub select
SELECT t.ID. t.Time FROM Table t
JOIN (SELECT ID, Max(Time) as Time FROM Table GROUP BY ID) ss
ON t.ID = ss.ID
ORDER BY ss.Time DESC, t.ID DESC, t.Time DESC
The sub select (ss) does the first query you have there, and joins it to the main table, letting you order by the highest(max) time for each ID, then by the ID and the Time for the row itself. Note that all the ordering is done on the final query, ordering in the sub select is useless, since the join will reorder it anyways.

SQL query for rolling changes

I have the following two tables:
1) Table name: period
+----------+
| PeriodID |
+----------+
| 1 |
| 2 |
| 3 |
| 4 |
+----------+
2) Table name: value
+-------------+--------+
| StartPeriod | Amount |
+-------------+--------+
| 1 | 100 |
| 3 | 200 |
+-------------+--------+
The first table represents time periods, like months. The second table represents the amount for each month, but only when it's different from the previous month. The amount starts at 100, stays at 100 for period 2, then jumps up to 200 beginning in period 3, and stays at 200 after that.
I need a query (MySQL) to return the amount for each period, like so:
+----------+--------+
| PeriodID | Amount |
+----------+--------+
| 1 | 100 |
| 2 | 100 |
| 3 | 200 |
| 4 | 200 |
+----------+--------+
So the query would return the Amount for the latest StartPeriod in the value table that's less than or equal to the PeriodID. For example, for PeriodID 2 it returns the Amount for StartPeriod 1 because there is no value for StartPeriod2 and 1 is the largest number less than or equal to 2 that has an Amount in the value table.
(Sorry the tables are so ugly)
Thank you!
You can do it using a correlated sub-query:
SELECT PeriodID,
(SELECT Amount
FROM Value
WHERE StartPeriod <= PeriodID
ORDER BY StartPeriod DESC LIMIT 1) AS Amount
FROM Period AS p
Demo here
Using variables probably performs better compared to the correlated sub-query:
SELECT PeriodID,
#amount := IF(Amount IS NOT NULL, Amount, #amount) AS Amount
FROM (
SELECT PeriodID, Amount
FROM Period AS p
LEFT JOIN Value AS v ON p.PeriodID = v.StartPeriod) AS t
CROSS JOIN (SELECT #amount := -1) AS var
ORDER BY PeriodID
Demo here
A simple subselect that selects the value for the highest startperiod lower or equal to the period-id could achive that:
select
periodid,
(select amount from value where startperiod <= periodid order by startperiod desc limit 1)
from period
order by periodid;
http://sqlfiddle.com/#!9/9f29c/3

How to get 2nd highest from table?

I have a table like this:
id | name | class | marks
1 | abc | 1 | 90
2 | cdf | 1 | 100
3 | xyz | 1 | 70
I want to get 2nd highest marks record. How can I get it with with one query. Simple and short?
SELECT * FROM `tableName` ORDER BY `marks` DESC LIMIT 1,1
Use LIMIT and ORDER
SELECT * FROM table
ORDER BY marks DESC LIMIT 1,1
ORDER BY marks DESC means: descending ordering, so highest on top.
LIMIT 1,1 means offset = 1 and only select 1 row.