I have a table with two columns.
+------+------+
| data | num |
+------+------+
| a | |
| a | |
| a | |
| b | |
| b |
Unfortunately, MySQL does not have windowing functions which is what you will need. So you will have to use something like this:
Final Query
select data, group_row_number, overall_row_num
from
(
select data,
@num := if(@data = `data`, @num + 1, 1) as group_row_number,
@data := `data` as dummy, overall_row_num
from
(
select data, @rn:=@rn+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
) x
order by data, overall_row_num
) x
order by overall_row_num
see SQL Fiddle with Demo
Explanation:
First, inner select, this applies a mock row_number
to all of the records in your table (See SQL Fiddle with Demo):
select data, @rn:=@rn+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
Second part of the query, compares each row in your table to the next one to see if it has the same value, if it doesn't then start the group_row_number
over (see SQL Fiddle with Demo):
select data,
@num := if(@data = `data`, @num + 1, 1) as group_row_number,
@data := `data` as dummy, overall_row_num
from
(
select data, @rn:=@rn+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
) x
order by data, overall_row_num
The last select, returns the values you want and places them back in the order you requested:
select data, group_row_number, overall_row_num
from
(
select data,
@num := if(@data = `data`, @num + 1, 1) as group_row_number,
@data := `data` as dummy, overall_row_num
from
(
select data, @rn:=@rn+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
) x
order by data, overall_row_num
) x
order by overall_row_num
Does the data have to stay in the order shown, or can we sort by the 'data' value?
If you can sort, then you only have to keep track of the current 'data' value, which can be done with variables:
set @last_data = null;
set @count = 0;
select data, @count,
case when @last_data is null or data != @last_data then @count := 1 else @count := @count + 1 end as new_count,
@last_data := data, @count
from t20120917
order by data;
If not, I think it'll be more complex...
it is something like this, but you will need to create procedure
create procedure procname()
begin
DECLARE done,i,j int DEFAULT 0;
DECLARE n,m nvarchar(500) DEFAULT '';
DECLARE cur CURSOR FOR SELECT d.data,d.num FROM tablename AS d ORDER BY DATA;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
OPEN cur;
read_loop: LOOP
set m = n;
SET j = i;
fetch cur into n,i;
IF n = m
THEN
SET i = i+1;
// UPDATE here your TABLE but you will need one more colomn to be able to UPDATE ONLY one RAW that you need
ELSE
SET i = 0; //RESET indexer
END IF;
IF done = 1 THEN
LEAVE read_loop;
END IF;
END LOOP read_loop;
CLOSE cur;
end
Here is a simple query that will do what you want.
select id,data,rownum
from (
select id,
data,
@row:=if(@prev=data,@row,0) + 1 as rownum,
@prev:=data
from tbl
order by data,id
)t
I have included an id on each row. But you don't need it.
Go fiddle: http://sqlfiddle.com/#!2/1d1f3/11/0
Credit: Want Row Number on Group of column in MY SQL?