Home Microsoft SQL Server Numbering rows in resultset using T-Sql

Polls

Who administers your corporate database infrastructure?
 

related links:

Numbering rows in resultset using T-Sql
User Rating: / 3
PoorBest 

     MS  SQL Server programmers and even administrators (making reports for managers from production database) quite often face the problem, that resulting record set must be numbered by some rule. For instance, top management wants the report of the best sold products grouped by category and ordered separetly within a particular category. Which would result in something like

Category

N

Product name

Total Sales, $

Tatal Sales, Qty

Food

1

Butter

11000

678

Food

2

Juice

10000

788

Food

3

Meat

4000

75

Materials

1

Rubber

14000

567

Materials

2

Steel

9000

234

Materials

3

Oil

5000

455

  Before advent of SQL Server 2005 it used to be a real headache to add this bugging N column to an existing query and thus record set.

  Suppose that we already wrote the query that returns necessary information and the only problem is to add the N column. Lets create the table and fill it in with the neccessary information.

 

create table salesresults (

    Category varchar(100)

  , ProductName  varchar(100)

  , TotalSalesMoney money

  , TotalSalesQuantity int

)

 

insert into salesresults (  Category , ProductName , TotalSalesMoney , TotalSalesQuantity )

select'Food'  ,  'Butter'  ,11000,  678

union all select'Food'  ,  'Juice'  ,10000,  788

union all select'Food'  ,  'Meat'  ,4000,  75

union all select'Materials'  ,  'Rubber'  ,14000,  567

union all select'Materials'  ,  'Steel'  ,9000,  234

union all select'Materials'  ,  'Oil'  ,5000,  455

 

 

select * from salesresults

 

So now we have the query that returns report, but how to add the number of product in category ?

If you use sql server 2000 you can use  a temporary table or table variable and update it with Number in cursor.

 

 

declare @a table (

   ID int identity (1,1)  primary key clustered

   ,Category varchar(100)

  , N int

  , ProductName  varchar(100)

  , TotalSalesMoney money

  , TotalSalesQuantity int

  )

  insert into @a (  Category , ProductName , TotalSalesMoney , TotalSalesQuantity )

  select   Category , ProductName , TotalSalesMoney , TotalSalesQuantity

  from salesresults

 

declare c cursor for select id, Category from @a order by Category, TotalSalesMoney desc

open c

declare @cat varchar(100)

declare @prev varchar(100)

declare @current int

declare @id int

set @prev=''

set @current = 1

fetch next from c into @id , @cat

while @@FETCH_STATUS = 0

begin

if @cat <> @prev

  set @current = 1

else

  set @current = @current + 1

set @prev = @cat

update @a set N = @current

where ID = @id

fetch next from c into @id , @cat

end

 

select * from @a

order by Category, N

close c

deallocate c

  Quite not simple script , is not it? You may also avoid using cursors.

create  table #a (

   ID int identity (1,1)

   ,Category varchar(100)

  , N int

  , ProductName  varchar(100)

  , TotalSalesMoney money

  , TotalSalesQuantity int

  )

  create clustered  index aid on #a (category, TotalSalesMoney desc )

  insert into #a (  Category , ProductName , TotalSalesMoney , TotalSalesQuantity )

  select   Category , ProductName , TotalSalesMoney , TotalSalesQuantity

  from salesresults

 

declare @prev varchar(100)

declare @current int

set @prev=''

set @current = 1

update a set

  @current =N= case when @prev <> Category then 1 else @current + 1 end

  ,@prev = Category

 from #a a

 

 

select * from #a

order by Category, N

drop table #a

  Here you need to have necesssary index (aid) on temporary table to have the rows ordered properly and thus numerated in right order.

 

 In MS SQL Server 2005 and later on you can use new operator ROW_NUMBER which does all the work described above for you.

Syntax of this operator is as following

 

ROW_NUMBER( )     OVER ( [ <partition_by_clause> ] <order_by_clause> )
<partition_by_clause>

Divides the result set produced by the FROM clause into partitions to which the ROW_NUMBER function is applied. For the PARTITION BY syntax, see OVER Clause (Transact-SQL).

<order_by_clause>

Determines the order in which the ROW_NUMBER value is assigned to the rows in a partition. For more information, see ORDER BY Clause (Transact-SQL). An integer cannot represent a column when the <order_by_clause> is used in a ranking function.

 So in over case we can use it as

 

select Category

 , N = ROW_NUMBER() OVER(partition by Category order by totalsalesmoney desc)

 , ProductName

  , TotalSalesMoney

  , TotalSalesQuantity

from salesresults

 

 

New operator ROW_NUMBER()  alows you to number resulting sets in any order you wish using only one line of sql code per row. Let say we need to number categories as well in our report.

 

 

 

 

Comments (0)

 
SPONSORED LINKS:
Content View Hits : 292354
DB-staff Remote DBA Services, Powered by DB-Staff 2008