37

I have a table: student_marks

marks
-----
  44
  55
  64
  98
  76

Expected output:

serial_number|marks
--------------------
  1          | 44
  2          | 55
  3          | 64
  4          | 98
  5          | 76

Using mysql user defined variables, it could be done using query:

 set  @a:=0;select @a:=@a+1 serial_number, marks from student_marks;

Is there any way to achieve this in msyql without using user defined variables?

sushil
  • 2,641
  • 3
  • 18
  • 24
  • 1
    possible duplicate of [MySQL - row number in recordset?](http://stackoverflow.com/questions/9285660/mysql-row-number-in-recordset) – Ja͢ck Jun 19 '12 at 04:42
  • Why don't you want to use user defined variables? – GarethD Jun 19 '12 at 06:09
  • I have to use two queries, one for initializing the mysql variable to 0 and another the actual query. I was trying to avoid two queries here. – sushil Jun 19 '12 at 06:13

13 Answers13

76

Based on your reasons for not wanting to use user defined variables as wanting to avoid having 2 queries, one for inializing and one to use it you could use the following:

SELECT  @a:=@a+1 serial_number, 
        marks 
FROM    student_marks,
        (SELECT @a:= 0) AS a;
GarethD
  • 68,045
  • 10
  • 83
  • 123
  • I wonder, how this works without `AS` keyword in SELECT statement? – xkeshav May 09 '13 at 05:45
  • 2
    @diEcho The [MySQL Docs](http://dev.mysql.com/doc/refman/5.0/en/select.html) state **The AS keyword is optional when aliasing a select_expr with an identifier.** See this [working example without AS on SQL Fiddle](http://www.sqlfiddle.com/#!2/0705e4/1) – GarethD May 09 '13 at 07:48
  • What if I want to loop through not just numbers but also all upper and lower case letters (i.e. creating a base 62 number sequence), and have it all left-padded with 0's? :D – Buttle Butkus Oct 22 '15 at 19:15
  • 1
    I suggest use of an explicit **cross join** instead. i.e. `FROM student_marks CROSS JOIN (SELECT @a:= 0) AS a;` so the intention is clear. – Paul Maxwell Oct 26 '15 at 01:05
  • But it is not working if i will order any another column with desc and asc – Kamlesh Sep 19 '16 at 04:35
  • The sequence will simply represent the order by clause that you use. If you need the results in a different order then you need to use a sub query with an order by to get the sequence, then the outer order by for the order that you need the results in. E.g. `SELECT Name, marks, serial_number FROM (SELECT ..... ORDER BY marks) As t ORDER BY Name;` this would apply the sequence based on marks, but the set would be ordered by name. – GarethD Sep 19 '16 at 07:41
  • @GarethD what if we have inner join query, then where to place this 2nd select? – Naila Akbar Jan 24 '18 at 12:36
  • 1
    @NullPointer You can also `INNER JOIN` to the query that initialises the variable, e.g. `SELECT @a:=@a+1 AS serial_number FROM T1 INNER JOIN T2 ON T2.ID = T1.ID INNER JOIN (SELECT @a:= 0) AS a;` - http://sqlfiddle.com/#!9/f155b4/1 – GarethD Jan 24 '18 at 13:16
11

Best Answer to this question should be the following, the best practice

SET @count:=0;
SELECT  (@count:=@count+1) AS serial_number, 
        marks 
FROM    student_marks
Kolajo
  • 147
  • 1
  • 4
  • Why did you reproduce the same answer as [the accepted one](https://stackoverflow.com/a/11096550/4074148) from 2012? – Veve Aug 31 '17 at 11:48
  • 2
    This is not same answer, moreover it quit faster than @GarethD's solution – Naveen DA Oct 09 '17 at 03:44
  • Just bad wording: he should have either suggested it as an alternative, or cited his evidence for "best practice". No reason to get angry or excited. – Parapluie Feb 23 '18 at 11:19
  • 1
    This is not the best answer to the question, since the OP specifically wanted a solution that uses one statement, not two. Moreover, the OP has already posted this solution as part of the question. So while may be a better approach if you can use more than one statement, it is not the best answer to *this* question. – GarethD Jul 13 '18 at 13:17
  • Note: This number won't be in sequence if you have ORDER BY – xjlin0 Jun 09 '22 at 00:21
1

I had a table with a column(c5) has contain a number x, I need a sql expression that repeated the same row x numbers of times:

my table A contains:

c1  c2  c3  c4  c5
16  1   2   16  3
16  1   2   17  2 
16  1   2   18  1

and I need:

c1  c2  c3  c4  c5  n
16  1   2   16  3   1
16  1   2   16  3   2
16  1   2   16  3   3
16  1   2   17  2   1
16  1   2   17  2   2
16  1   2   18  1   1

I solved That with the expression:

SELECT
    c1, c2, c3, c4, c5, row_number AS n
FROM
    (
        SELECT
            @curRow := @curRow + 1 AS row_number
        FROM
            tablea
        JOIN (SELECT @curRow := 0) r
        WHERE
            @curRow < (
                SELECT
                    max(field1)
                FROM
                    tablea
            )
    ) AS vwtable2
LEFT JOIN tablea d ON vwtable2.row_number <= tablea.field1;
1

tested in mysql 5.6:

SELECT
    @a:=@a+1 as serial_number,
    student.* 
FROM
    student
join (SELECT @a:= 0) a
qiangbro
  • 128
  • 1
  • 9
1

you can add serial number with this query :

set @counter=0;
SELECT  @counter:=@counter+1 as serial_number from <table_name>

output :

   |...............................|
   | serial_number  |   first_name |
   |...............................|
   |      1         |    mojtaba   |
   |      2         |    athena    |
   |      3         |     azin     |
   |      4         |     ava      |
   |      5         |    arash     |
   |...............................|

in addition if you want to use in where

set @counter=0;
select serial_number from (SELECT  @counter:=@counter+1 as serial_number 
from <table_name>) as tbl_counter where serial_number > 3

output :

   |...............................|
   | serial_number  |   first_name |
   |...............................|
   |      4         |     ava      |
   |      5         |    arash     |
   |...............................|
hassanzadeh.sd
  • 3,091
  • 1
  • 17
  • 26
1

I found simple way to generate serial number

select ROW_NUMBER() over (PARTITION by '1') AS serial_number,customer_id from users;

Also it support pagination

  • simplest one, however it existed in 2022 (supported by mysql 8), did not exist in earlier versions – Sami Aug 17 '23 at 08:45
0

No, there isn't. But you could produce the serial_number in program side, not the database side.

xdazz
  • 158,678
  • 38
  • 247
  • 274
  • Yes, that can be done. I have already generated serial number using mysql user defined variables as well. I was wondering if there are some alternate ways in mysql to achieve this. – sushil Jun 19 '12 at 04:54
0

None of the above answers seemed satisfactory as you would need to initialize the variable as null in a separate query.

So posting the below all encompassing solution:

SELECT ROUND(@a:=@a+1,0) sr_num, t.* from (select @a:=0) initvars, your_table t;
Faisal
  • 4,591
  • 3
  • 40
  • 49
0

@a:=@a+1 serial_no,

CROSS JOIN (SELECT @a:= 0) AS a

SELECT @a:=@a+1 serial_no, sc.id, sc.name, sc.address, c.country,s.state 
FROM oc_table1 sc CROSS JOIN (SELECT @a:= 0) AS a LEFT JOIN oc_table2 .......
Sam Prasanna
  • 131
  • 1
  • 3
0

ALTER TABLE table_name ADD COLUMN sr_no INT UNIQUE NOT NULL AUTO_INCREMENT FIRST;

This will even edit your main table in case you forgot to create a column for serial numbers. You can also use this to add sr_no column to two different columns and easily join them (or create a new table using both of them).

-1

Why don't you make it an auto-increment field?

http://dev.mysql.com/doc/refman/5.0/en/example-auto-increment.html

Mario The Spoon
  • 4,799
  • 1
  • 24
  • 36
  • For simplicity of asking question, I created this table. Actually, I have to add a serial number to a result which I will get by joining two tables. – sushil Jun 19 '12 at 04:52
-1

No, unless you have a column which containes these numbers.

CloudyMarble
  • 36,908
  • 70
  • 97
  • 130
-1

Though very late for the answer, generating the sequential ids without having two queries and without using joins and without using sub query.

SELECT *, (@cnt := if(@cnt IS NULL, 0,  @cnt) + 1) AS id FROM table_name;

Cheers

Abhishek Madhani
  • 1,155
  • 4
  • 16
  • 26