Select every 'nth row in descending order - mysql

SELECT * FROM ( SELECT #row := #row +1 AS rownum, [column name] FROM ( SELECT * FROM [table name] ) WHERE rownum % 5 = 1
This does indeed return every 5th row, but in ascending order. What I want is that it first gets all the data, put them in descending order and THEN apply the filter.
If you filter it first and then put it in descending order, it will not start with the latest data added (4/5th of the time).
I would like to know how one should do this.
Thanks in advance
Edit: For people with the same problem, this is what I used:
SELECT * FROM
(SELECT rank, id, Temperature FROM
(SELECT *, #rownum := #rownum + 1 AS rank FROM temperature_room1,
(SELECT #rownum := 0) r) AS T ORDER BY id DESC) AS J WHERE rank % 5 = 1
Select everything from:
Select rank, id and Temperature from:
Select everything and rownumber as rank from the table as t ordered by ID in descending order
Finally, only output the row numbers which can be divided by 5 and the remainder is 1
Don't quote me on this, I'm a big noob regarding SQL stuff. It works for me, so I'm happy.

seems like you just need an order by dec on the desired column in one of the three queries. I think the second one as order by applies to the select at the same level. ans since you want your rownum ordered desc... seems like that's the place...
SELECT *
FROM ( SELECT #row := #row +1 AS rownum, [column name]
FROM ( SELECT * FROM [table name] )
ORDER BY [column name] desc
)
WHERE rownum % 5 = 1

Related

Trying to put a variable into limit to find a median

I trying to use mysql to solve the following solutions:
https://www.hackerrank.com/challenges/weather-observation-station-20/problem
Understanding that a variable cannot be put into LIMIT statement (from this )
My approach>
to declare a new variable to record rowIDs, and use rowID to retrieve the record in the middle.
However, it seems that rowID is not working well.
Could anyone give me some advises?
SELECT ROUND(COUNT(LAT_N)/2,0) FROM STATION into #count;
SELECT ROUND(a.LAT_N,4) FROM (
SELECT *,#row := #row + 1 FROM STATION s, (SELECT #row := 0) r
WHERE #row <=#count
ORDER BY s.LAT_N ASC) a
ORDER BY a.LAT_N DESC LIMIT 1;`
If you are running MySQL 8.0, this is simpler done with window functions:
select round(avg(lat_n), 4) median_lat_n
from (
select s.*, row_number() over(orer by lat_n) rn
from station s
where lat_n is not null
) s
where rn * 2 in (rn - 1, rn, rn + 1)
In earlier versions, variables make it bit tricky; we need one more level of nesting to make it safe:
select round(avg(lat_n), 2) median_lat_n
from (
select s.*, #rn := #rn + 1 rn
from (select * from station order by lat_n) s
cross join (select #rn := 0) p
) s
where rn * 2 in (rn - 1, rn, rn + 1)
The logic is as follows: first enumerate the rows, ordered by lat_n. If the row count is uneven, we pick the middle row; if it is even, we take the average of the two middle values.

How to extract alternate rows from a table which has two rows(Employ_id, salary)?

I have a table with two rows(employeeId, salary), Now I want to extract alternate rows(even or odd) from that table. how to write code in sql?
Assuming you have a column that specifies the ordering of the table, then you can use variables to do what you want:
select t.*
from (select t.*, (#rn := #rn + 1) as seqnum
from table t cross join
(select #rn := 0) vars
order by col
) t
where mod(seqnum, 2) = 0;
ODD ROWS,
select * from
(select empno, ename, sal, rownum rn
from emp
order by empno)
where mod (rn, 2) <> 0;
EVEN ROWS
select * from
(select empno, ename, sal, rownum rn
from emp
order by empno)
where mod (rn, 2) = 0;
SQL tables represent unordered sets, so there is no such thing as "even" and "odd" rows. If I interpret the question as wanting rows where employeeid is even or odd, I would use:
where mod(employeeid, 2) = 0 -- or 1 or odd
If I interpret it as wanted rows -- ordered by employeeid -- were even or odd, then I would enumerate the rows. In the most recent versions of MySQL:
select t.*
from (select t.*,
row_number() over (order by employeeid) as seqnum
from t
) t
where mod(seqnum, 2) = 0; -- or 1 for odd

MySQL: Limiting result for WHERE IN list

Let's say there are millions of records in my_table.
Here is my query to extract rows with a specific name from list:
SELECT * FROM my_table WHERE Name IN ('name1','name2','name3','name4')
How do I limit the returned result per name1, name2, etc?
The following query would limit the whole result (to 100).
SELECT * FROM my_table WHERE Name IN ('name1','name2','name3','name4') LIMIT 100
I need to limit to 100 for each name.
This is a bit of a pain in MySQL, but the best method is probably variables:
select t.*
from (select t.*,
(#rn := if(#n = name, #rn + 1,
if(#n := name, 1, 1)
)
) as rn
from my_table t cross join
(select #n := '', #rn := 0) params
order by name
) t
where rn <= 100;
If you want to limit this to a subset of the names, then add the where clause to the subquery.
Note: If you want to pick certain rows -- such as the oldest or newest or biggest or tallest -- just add a second key to the order by in the subquery.
Try
SELECT * FROM my_table WHERE Name IN ('name1','name2','name3','name4') FETCH FIRST 100 ROWS ONLY

Hide ROW_NUMBER() in subquery

I have a query like
Select *
From y
WHERE y.z = (
SELECT a, (adding rownumber here)
FROM b
)
I want to add a clause where it only selects every second row. To do this I need to add row_number() to the subquery, and have a clause where rownumber % 2 = 0.
My question is, am I able to add rownumber to the select of the subquery and somehow hide it so it doesn't affect the query
Rownumbering in MySQL is a notorious pain in the neck.
You can number your rows in MySQL like this.
SELECT (#rownum := #rownum+1) rownum, b.*
FROM b
JOIN (SELECT #rownum := 0) init
ORDER BY b.whatever
Don't forget the ORDER BY clause here. Without explicit ordering the query engine is free to randomize the order of rows it returns.
Then, you can use that mess as a subquery and do things with the rownum.
SELECT *
FROM (
SELECT (#rownum := #rownum+1) rownum, b.*
FROM b
JOIN (SELECT #rownum := 0) init
ORDER BY b.whatever
) table_with_rownum
WHERE rownum % 2 = 0
If you don't want to show the rownumbers, change your SELECT from SELECT * to SELECT col, col, col and leave out rownum.

Rank in MySQL table

I have a MySQL table called "MyTable" and it basically lists usernames and points (two columns, name and points). I want to say something like "what is joe1928's rank?", which of course is based off his points. How could I do this in MySQL without having to download all that data and sort it and determine the rank myself?
The person with the highest number of points would be ranked 1.
Try getting the number of people with a higher score than your user:
select count(*) from MyTable where score > (select score from MyTable where user = 'Joe');
That will return 0 for the top user.
This page seems to describe and solve your problem.
Notes from that page:
SET #rownum := 0;
SELECT rank, correct FROM (
SELECT #rownum := #rownum + 1 AS rank, correct, uid
FROM quiz_user ORDER BY correct DESC
) as result WHERE uid=xxxxxxxx
SELECT #r AS Rank
FROM MyTable u, (SELECT #r := 0)
WHERE (#r := #r + 1) * (u.Username = 'joe1928')
ORDER BY u.Score DESC
LIMIT 1
select * from [TABLENAME] where [USERNAME] = blah order by [POINTS] desc limit 1;
Based on the link posted by #Dave your query will look like something below:
select Rank,name from
(select #rownum:=#rownum+1 AS 'Rank', p.name
from calls p, (select #rownum:=0) r
order by p.points desc) as rankResults
where name = 'joe';
This is from another stack overflow page, seems to solve your problem.
SELECT uo.*,
(
SELECT COUNT(*)
FROM users ui
WHERE (ui.points, ui.id) >= (uo.points, uo.id)
) AS rank
FROM users uo
WHERE id = #id