MySQL: How to ORDER BY and SET ids? - mysql

I already googled but couldn't find a solution.
I have two columns called order_id and name. I want to ORDER BY name and then SET ascending order_id.
Like this:
order_id name
1 Arya
2 Herbert
3 Paul
4 Peter
5 Tiffany
My id column is int(4) and by default value is 0. It's not PRIMARY or UNIQUE. (It'a also not the main id. Main id is of course PRIMARY.
How can I do this with SQL?

You could use ROW_NUMBER(MySQL 8.0+):
SELECT name, ROW_NUMBER() OVER(ORDER BY name) AS rn
FROM tab
ORDER BY rn;
Update:
UPDATE tab
SET order_id = (SELECT rn FROM (SELECT name,ROW_NUMBER() OVER(ORDER BY name) AS rn
FROM tab)s
WHERE s.name = tab.name); -- assuming that name is UNIQUE
DBFidde Demo

For versions < 8.0 you can use this:
select #rn := 0;
UPDATE tbl T1
JOIN (select #rn := #rn + 1 rn, `name` from tbl order by `name`) T2
ON T1.`name` = T2.`name`
SET T1.order_id = T2.rn
Demo
Useful article related to your problem: MySQL UPDATE JOIN

As your mysql version is below 8.0 so you have to manually generate orderid
below can help you
select t.*,
#rownum := #rownum + 1 AS order_id from
(
select * from
tab o order by name asc
) as t , (SELECT #rownum := 0) r
http://www.sqlfiddle.com/#!9/ae3fda/3

Related

MySQL convert duplicate field entries to duplicate incrementing value

I currently have a table that has a parent_id field for multiple entries, ie the same ID number for 4 entries (as per the screenshot below). I would like to convert the parent_id to run from 9000 upwards, so in the screenshot 000004 would become 9000 in 4 entries, 000007 would become 9001 in 4 entries and so on (as shown in the example outcome). Does anyone know of an easy way to implement this please as I'd rather not have to manually change 2224 entries!?
Thanks in advance guys!
Table screenshot:
Example outcome:
You seem to want an update. If so:
update t join
(select t.*, row_number() over (order by id) as seqnum
from t
) tt
on t.id = tt.id
set t.parent_id = 9000 + floor( (seqnum - 1) / 4);
Note that this ignores the current parent_id, assigning the same value to groups of 4 rows based on the id.
EDIT:
In older versions of MySQL:
update t join
(select t.*, (#rn := #rn + 1) as seqnum
from (select t.* from t order by id) t cross join
(select #rn := 0) params
) tt
on t.id = tt.id
set t.parent_id = 9000 + floor( (seqnum - 1) / 4);
If you are runnig MySQL 8.0, you can use dense_rank() for this:
select
t.*,
8999 + dense_rank() over(order by parent_id) new_parent_id
from mytable t
On earlier versions, one (less efficient) option uses a correlated subquery:
select
t.*,
9000 + (select count(distinct t1.parent_i) from mytable t1 where t1.parent_id < t.parent_id) new_parent_id
from mytable t

How can i filter few repeatation in MySQL Query

I have a mysql table like below. It used to store document with versioning.
I want to select a docid of latest (with higest major version and minor version). It will eleminate all same doc id only fetch the document with highest major_version & minor_version. So i want result as below.
In MySQL 8.0, you can filter with row_number():
select *
from (
select
t.*,
row_number() over(partition by id, docid order by major_version, minor_version) rn
from mytable t
) t
where rn = 1
In earlier versions, you can filter with a correlated subquery. Assuming that you have a primary key in the table, say column pk, you can do:
select t.*
from mytable t
where t.pk = (
select t1.pk
from mytable t1
where t1.id = t.id and t1.docid = t.docid
order by t1.major_version desc, t1.minor_version desc
limit 1
)
For performance, consider an index on (id, docid, major_version, minor_version).
Without a unique column that can be used as primary key, it is a bit more complicated. One way to do it is to use not exists:
select t.*
from mytable t
where not exists (
select 1
from mytable t1
where
t1.id = t.id
and t1.docid = t.docid
and (
t1.major_version > t.major_version
or (t1.major_version = t.major_version and t1.minor_version > t.minor_version)
)
)
One method uses row_number():
select t.*
from (select t.*,
row_number() over (partition by docid order by major_version desc, minor_version desc) as seqnum
from t
) t
where seqnum = 1;
This is a pain in earlier versions. Probably the simplest and most efficient method is to use variables:
select t.*
from (select t.*,
(#rn := if(#d = docid, #rn + 1,
if(#d := docid, 1, 1)
)
) as rn
from (select t.*
from t
order by docid, major_version desc, minor_version desc
) t cross join
(select #rn := 0, #d := '') params
) t
where rn = 1;

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

How to select certain numbers of groups in MySQL?

I have the table with data:
And for this table I need to create pegination by productId column. I know about LIMIT N,M, but it works with rows and not with groups. For examle for my table with pegination = 2 I expect to retrieve all 9 records with productId = 1 and 2 (the number of groups is 2).
So how to create pegination by numbers of groups ?
I will be very thankfull for answers with example.
One way to do pagination by groups is to assign a product sequence to the query. Using variables, this requires a subquery:
select t.*
from (select t.*,
(#rn := if(#p = productid, #rn + 1,
if(#rn := productid, 1, 1)
)
) as rn
from table t cross join
(select #rn := 0, #p := -1) vars
order by t.productid
) t
where rn between X and Y;
With an index on t(productid), you can also do this with a subquery. The condition can then go in a having clause:
select t.*,
(select count(distinct productid)
from t t2
where t2.productid <= t.productid)
) as pno
from t
having pno between X and Y;
Try this:
select * from
(select * from <your table> where <your condition> group by <with your group>)
LIMIT number;

Mysql query to get the row position in a table

I have table with id (store user id) and score in different match. I want what is the position of a user.
So for i try this sql fiddle;
in this I am getting all the row but I need only user having id 3 and it position in the table.
like this:
Score Postion
26 3
Even i try to do like this but no success
MySql: Find row number of specific record
With MySQL, how can I generate a column containing the record index in a table?
I got the answer: http://sqlfiddle.com/#!2/b787a/2
select * from (
select T.*,(#rownum := #rownum + 1) as rownum from (
select sum(score) as S,id from mytable group by id order by S desc ) as T
JOIN (SELECT #rownum := 0) r
) as w where id = 3
Updated sqlfiddle and above query. Now it is working perfectly.
I think this should do the trick:
SELECT totalScore, rownum FROM (
SELECT id,sum(score) AS totalScore,(#rownum := #rownum + 1) AS rownum
FROM mytable
JOIN (SELECT #rownum := 0) r
group by id) result
WHERE result.ID = 3;
just add a where clause
select x.id,x.sum,x.rownum
from(
select id,sum(score) as sum,(#rownum := #rownum + 1) as rownum
from mytable
JOIN (SELECT #rownum := 0) r
group by id
) x
where id =3