MySQL. Получите счетчик для каждого повторяющегося значения.
У меня есть таблица с двумя столбцами.
+------+------+
| data | num |
+------+------+
| a | |
| a | |
| a | |
| b | |
| b | |
| c | |
| d | |
| a | |
| b | |
+------+------+
Я хочу, чтобы столбец "num" отображал инкрементный счетчик для каждой повторяющейся записи:
+------+------+
| data | num |
+------+------+
| a | 1 |
| a | 2 |
| a | 3 |
| b | 1 |
| b | 2 |
| c | 1 |
| d | 1 |
| a | 4 |
| b | 3 |
+------+------+
Можно ли это сделать без каких-либо других скриптов помимо запроса mySQL?
UPDATE:
расширенный вопрос здесь
Ответы
Ответ 1
К сожалению, у MySQL нет функций окон, которые вам нужны. Поэтому вам нужно будет использовать что-то вроде этого:
Окончательный запрос
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:[email protected]+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
) x
order by data, overall_row_num
) x
order by overall_row_num
см. SQL Fiddle with Demo
Объяснение:
Во-первых, внутренний выбор, это относится к mock row_number
ко всем записям в вашей таблице (см. SQL Fiddle with Demo):
select data, @rn:[email protected]+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
Вторая часть запроса сравнивает каждую строку в таблице с следующей, чтобы увидеть, имеет ли она одно и то же значение, если она не запускает group_row_number
(см. 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:[email protected]+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
) x
order by data, overall_row_num
Последний выбор, возвращает нужные значения и помещает их обратно в запрошенном порядке:
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:[email protected]+1 overall_row_num
from yourtable, (SELECT @rn:=0) r
) x
order by data, overall_row_num
) x
order by overall_row_num
Ответ 2
Вот простой запрос, который сделает то, что вы хотите.
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
Я включил идентификатор в каждую строку. Но вам это не нужно.
Go fiddle: http://sqlfiddle.com/#!2/1d1f3/11/0
Кредит: Хотите номер строки в группе столбца в MY SQL?
Ответ 3
Должны ли данные оставаться в указанном порядке или мы можем сортировать по значению "данные"?
Если вы можете сортировать, вам нужно только отслеживать текущее значение "данных", которое может быть выполнено с помощью переменных:
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;
Если нет, я думаю, что это будет сложнее...
Ответ 4
это что-то вроде этого, но вам нужно будет создать процедуру
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