Подтвердить что ты не робот

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:

расширенный вопрос здесь

4b9b3361

Ответ 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

Ответ 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