Use of Rank function to extract a list of rows with the highest date

Today I had the problem to create a query to get the most recent price from a pricelists table. Every pricelist in the table can contain the same article any number of times with different startup dates. I made some search to find a way to obtain what i needed and I found the RANK function, it was used in a similar scenario. I publish this post as usual to remember how to use this function next time I need it and in the hope to help someone else solving similar problems.

The table:

CREATE TABLE [dbo].[TbPricelistsRg](
    [IDPriceListRg] [int] NOT NULL,
    [IDPriceList] [nvarchar](10) NOT NULL,
    [IDArticle] [nvarchar](32) NULL,
    [Price] [decimal](18, 5) NULL,
    [StartDate] [date] NULL,
 CONSTRAINT [PK_TbPriceListsRg] PRIMARY KEY CLUSTERED 
(
    [IDPriceListRg] ASC
)WITH (PAD_INDEX  = OFF, STATISTICS_NORECOMPUTE  = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS  
= ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY] ) ON [PRIMARY]

Every row is linked to a PriceList through the IDPriceLIst field, we don’t need to use it for the example so it is omitted.

INSERT INTO [dbo].[TbPricelistsRg]
           ([IDPriceList]
           ,[IDArticle]
           ,[Price]
           ,[StartDate])
     VALUES
           ('CLD'
           ,'ABC'
           ,10
           ,CONVERT(date, '20080105', 112))
GO

INSERT INTO [dbo].[TbPricelistsRg]
           ([IDPriceList]
           ,[IDArticle]
           ,[Price]
           ,[StartDate])
     VALUES
           ('CLD'
           ,'OCQ'
           ,14
           ,CONVERT(date, '20080105', 112))
GO

INSERT INTO [dbo].[TbPricelistsRg]
           ([IDPriceList]
           ,[IDArticle]
           ,[Price]
           ,[StartDate])
     VALUES
           ('CLD'
           ,'FYS'
           ,21
           ,CONVERT(date, '20080105', 112))
GO

INSERT INTO [dbo].[TbPricelistsRg]
           ([IDPriceList]
           ,[IDArticle]
           ,[Price]
           ,[StartDate])
     VALUES
           ('CLD'
           ,'MUI'
           ,13
           ,CONVERT(date, '20080105', 112))
GO

INSERT INTO [dbo].[TbPricelistsRg]
           ([IDPriceList]
           ,[IDArticle]
           ,[Price]
           ,[StartDate])
     VALUES
           ('CLD'
           ,'SIO'
           ,42
           ,CONVERT(date, '20080105', 112))
GO

INSERT INTO [dbo].[TbPricelistsRg]
           ([IDPriceList]
           ,[IDArticle]
           ,[Price]
           ,[StartDate])
     VALUES
           ('CLD'
           ,'GOU'
           ,18
           ,CONVERT(date, '20080105', 112))
GO

INSERT INTO [dbo].[TbPricelistsRg]
           ([IDPriceList]
           ,[IDArticle]
           ,[Price]
           ,[StartDate])
     VALUES
           ('CLD'
           ,'HOU'
           ,20
           ,CONVERT(date, '20080105', 112))
GO

The previous script inserts some articles, we can repeat it changing the PriceLIst, the Dates and prices to be able to show how the query meets our needs.

SELECT [IDPriceListRg]
      ,[IDPriceList]
      ,[IDArticle]
      ,[Price]
      ,[StartDate]
      ,RANK() OVER (PARTITION BY IDPriceList, IDArticle ORDER BY StartDate DESC) DATERANK
  FROM [paperinik].[dbo].[TbPricelistsRg]

 

The RANK function, allows us to indicate one or more grouping fields on which calculate ranking, this is done using the PARTITION BY keywords, in our query we indicate the two fields on which ranking has to break. The ORDER BY  keyword, instead indicates on which field we have to measure ranking. while the DESC keywords tells that we want to start from the most recent date..

This is the result of our query.

IDListinoRg IDListino IDArticolo Prezzo ValidoDal DATERANK
107 CLD ABC 1.000.000 24/10/2010 1
86 CLD ABC 1.000.000 15/05/2010 2
65 CLD ABC 1.000.000 08/01/2010 3
44 CLD ABC 1.000.000 08/09/2009 4
23 CLD ABC 1.000.000 16/04/2009 5
1 CLD ABC 1.000.000 05/01/2008 6
2 CLD ABC 1.000.000 05/01/2008 6
109 CLD FYS 2.100.000 24/10/2010 1
88 CLD FYS 2.100.000 15/05/2010 2
67 CLD FYS 2.100.000 08/01/2010 3
46 CLD FYS 2.100.000 08/09/2009 4
25 CLD FYS 2.100.000 16/04/2009 5
4 CLD FYS 2.100.000 05/01/2008 6
112 CLD GOU 1.800.000 24/10/2010 1
91 CLD GOU 1.800.000 15/05/2010 2
70 CLD GOU 1.800.000 08/01/2010 3
49 CLD GOU 1.800.000 08/09/2009 4
28 CLD GOU 1.800.000 16/04/2009 5
7 CLD GOU 1.800.000 05/01/2008 6
113 CLD HOU 2.000.000 24/10/2010 1
92 CLD HOU 2.000.000 15/05/2010 2
71 CLD HOU 2.000.000 08/01/2010 3
50 CLD HOU 2.000.000 08/09/2009 4
29 CLD HOU 2.000.000 16/04/2009 5
8 CLD HOU 2.000.000 05/01/2008 6

So to obtain the most recent prices, we need just to add a filter on DATERANK = 1, and to obtain the less recent price we just need to delete the DESC keyword and filter on rank 1.

Technorati Tag: ,,

Print | posted on mercoledì 7 luglio 2010 23.45

Feedback

No comments posted yet.

Your comment:





 
Please add 5 and 2 and type the answer here:

Copyright © Sabrina C.

Design by Bartosz Brzezinski

Design by Phil Haack Based On A Design By Bartosz Brzezinski