Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQLServer SQL query with a row counter

Tags:

I have a SQL query, that returns a set of rows:

SELECT id, name FROM users where group = 2 

I need to also include a column that has an incrementing integer value, so the first row needs to have a 1 in the counter column, the second a 2, the third a 3 etc

The query shown here is just a simplified example, in reality the query could be arbitrarily complex, with several joins and nested queries.

I know this could be achieved using a temporary table with an autonumber field, but is there a way of doing it within the query itself ?

like image 848
andynormancx Avatar asked Jan 29 '09 17:01

andynormancx


People also ask

How do I get row count in SQL SELECT query?

To counts all of the rows in a table, whether they contain NULL values or not, use COUNT(*). That form of the COUNT() function basically returns the number of rows in a result set returned by a SELECT statement.

How do I count rows in SQL Server?

The ROWCOUNT Set Function causes the server to stop the query processing after the specified number of records is returned. One may limit the number of records returned by all subsequent SELECT statements within the session by using the keyword SET ROWCOUNT.

How do I add a counter to a SQL query?

set @anyVariableName=0; select yourColumnName, @anyVariableName:=@anyVariableName+1 as anyVariableName from yourTableName; To understand the above syntax and set an increment counter, let us first create a table. The query to create a table is as follows. Insert some records in the table using insert command.

How do I display row numbers with records in SQL?

Here is the result set. To add a row number column in front of each row, add a column with the ROW_NUMBER function, in this case named Row# . You must move the ORDER BY clause up to the OVER clause. SELECT ROW_NUMBER() OVER(ORDER BY name ASC) AS Row#, name, recovery_model_desc FROM sys.


2 Answers

For starters, something along the lines of:

SELECT my_first_column, my_second_column,     ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter FROM my_table 

However, it's important to note that the ROW_NUMBER() OVER (ORDER BY ...) construct only determines the values of Row_Counter, it doesn't guarantee the ordering of the results.

Unless the SELECT itself has an explicit ORDER BY clause, the results could be returned in any order, dependent on how SQL Server decides to optimise the query. (See this article for more info.)

The only way to guarantee that the results will always be returned in Row_Counter order is to apply exactly the same ordering to both the SELECT and the ROW_NUMBER():

SELECT my_first_column, my_second_column,     ROW_NUMBER() OVER (ORDER BY my_order_column) AS Row_Counter FROM my_table ORDER BY my_order_column  -- exact copy of the ordering used for Row_Counter 

The above pattern will always return results in the correct order and works well for simple queries, but what about an "arbitrarily complex" query with perhaps dozens of expressions in the ORDER BY clause? In those situations I prefer something like this instead:

SELECT t.* FROM (     SELECT my_first_column, my_second_column,         ROW_NUMBER() OVER (ORDER BY ...) AS Row_Counter  -- complex ordering     FROM my_table ) AS t ORDER BY t.Row_Counter 

Using a nested query means that there's no need to duplicate the complicated ORDER BY clause, which means less clutter and easier maintenance. The outer ORDER BY t.Row_Counter also makes the intent of the query much clearer to your fellow developers.

like image 87
LukeH Avatar answered Oct 13 '22 22:10

LukeH


In SQL Server 2005 and up, you can use the ROW_NUMBER() function, which has options for the sort order and the groups over which the counts are done (and reset).

like image 33
Cade Roux Avatar answered Oct 13 '22 22:10

Cade Roux