Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
552 views
in Technique[技术] by (71.8m points)

sql - MySQL - Get a counter for each duplicate value

I have a table with two columns.

+------+------+
| data | num ?| 
+------+------+
| a  ? | ? ?  | 
| a ?  | ? ?  |
| a ?  | ? ?  |
| b ?  | ? ?  |
| b ?  | ? ?  |
| c ?  | ? ?  |
| d ?  | ? ?  |
| a ?  | ? ?  |
| b ?  | ? ?  | 
+------+------+

I want the column "num" displays an incremental counter for each duplicate entry:

+------+------+
| data | num ?| 
+------+------+
| a  ? | ? ?1 | 
| a ?  | ? ?2 |
| a ?  | ? ?3 |
| b ?  | ? ?1 |
| b ?  | ? ?2 |
| c ?  | ? ?1 |
| d ?  | ? ?1 |
| a ?  | ? ?4 |
| b ?  | ? ?3 | 
+------+------+

Is this possible to be done without any other scripting besides a mySQL query?

UPDATE:

extended question here

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...