Please start any new threads on our new
site at https://forums.sqlteam.com. We've got lots of great SQL Server
experts to answer whatever question you can come up with.
| Author |
Topic |
|
LGOOLSBY
Starting Member
4 Posts |
Posted - 2007-03-19 : 14:29:39
|
I need to query for the top 3 records in each group. For example, If I run a query for SELECT PAYER, CODE, PRICE, ALLOWABLE FROM CODERATES ORDER BY PAYER, CODE, ALLOWABLE I will be returned a list of some 70000 records. For Each CODE withinn a PAYER, I want to see the TOP 3 ALLOWABLES (a dollar amount.)I can use TOP 3 and get just the TOP 3 allowables but I want the top 3 allowables for each CODE within a PAYER. I hope that I have not lost you in my wording. I would love to know how to do this using SQL.Any help?Thanks, |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-03-19 : 14:36:32
|
| [code]-- Stage the dataDECLARE @Stage TABLE (RecID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED, Payer VARCHAR(20), Code VARCHAR(20), Price MONEY, Allowable INT, Grp INT)INSERT @Stage (Payer, Code, Price, Allowable)SELECT Payer, Code, Price, AllowableFROM CodeRatesORDER BY Payer, Code, Allowable DESC-- Initialize ORDERINGDECLARE @PrevPayer VARCHAR(20), @PrevCode VARCHAR(20), @Grp INTSELECT @PrevPayer = CHAR(9), @PrevCode = CHAR(9)UPDATE sSET @Grp = Grp = CASE WHEN Payer = @PrevPayer AND Code = @PrevCode THEN @Grp + 1 ELSE 1 END, @PrevPayer = Payer, @PrevCode = CodeFROM @Stage AS s-- Show the expected outputSELECT Payer, Code, Price, AllowableFROM @StageWHERE Grp BETWEEN 1 AND 3ORDER BY RecID[/code]Peter LarssonHelsingborg, Sweden |
 |
|
|
spirit1
Cybernetic Yak Master
11752 Posts |
Posted - 2007-03-19 : 14:47:35
|
| http://weblogs.sqlteam.com/mladenp/archive/2005/08/01/7421.aspxpoint 2._______________________________________________Causing trouble since 1980blog: http://weblogs.sqlteam.com/mladenp |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-03-19 : 15:09:35
|
| Up for a speed test on 70000 records?I would estimate the method above to take about less than 10 seconds including staging.And I think #2 blog point will take more than 100 seconds.Peter LarssonHelsingborg, Sweden |
 |
|
|
spirit1
Cybernetic Yak Master
11752 Posts |
Posted - 2007-03-19 : 15:24:24
|
| true..._______________________________________________Causing trouble since 1980blog: http://weblogs.sqlteam.com/mladenp |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-03-19 : 17:42:54
|
| The difference was not that much!On average, the #2 point was half as fast as the other method.And #2 method also only updated one sequency...Peter LarssonHelsingborg, Sweden |
 |
|
|
SwePeso
Patron Saint of Lost Yaks
30421 Posts |
Posted - 2007-03-19 : 17:45:01
|
| [code]SET NOCOUNT ON-- Prepare sample dataDECLARE @Sample TABLE ( Col1 VARCHAR(2), Col2 VARCHAR(2) )DECLARE @i INTSELECT @i = 700000WHILE @i > 0 BEGIN INSERT @Sample (Col1, Col2) SELECT LEFT(c, 2), RIGHT(c, 2) FROM ( SELECT SUBSTRING(CAST(NEWID() AS VARCHAR(36)), 10, 4) AS c ) AS x SET @i = @i - 1 ENDdeclare @dt datetime, @d intset @dt = current_timestamp-- Stage the dataDECLARE @Stage TABLE (RecID INT IDENTITY(1, 1) PRIMARY KEY CLUSTERED, Col1 VARCHAR(2), Col1Seq INT, Col2 VARCHAR(2), Col2Seq INT)INSERT @Stage (Col1, Col2)SELECT Col1, Col2FROM @SampleORDER BY Col1, Col2-- Initialize ORDERINGDECLARE @PrevCol1 VARCHAR(2), @PrevCol2 VARCHAR(2), @Col1Seq INT, @Col2Seq INTSELECT @PrevCol1 = CHAR(9), @PrevCol2 = CHAR(9)UPDATE sSET @Col1Seq = Col1Seq = CASE WHEN Col1 = @PrevCol1 THEN @Col1Seq ELSE ISNULL(@Col1Seq, 0) + 1 END, @Col2Seq = Col2Seq = CASE WHEN Col1 = @PrevCol1 THEN @Col2Seq + 1 ELSE 1 END, @PrevCol1 = Col1, @PrevCol2 = Col2FROM @Stage AS s-- Show the expected outputselect @d = count(*) from (SELECT Col1, Col1Seq, Col2, Col2SeqFROM @StageWHERE Col2Seq BETWEEN 1 AND 3--ORDER BY RecID) as eselect datediff(ms, @dt, current_timestamp) / 1000.0set @dt = current_timestampcreate table #s (col1 varchar(2), col2 varchar(2))insert #s (col1, col2)select col1, col2from @sample order by col1, col2CREATE clustered INDEX IX_1 ON #s (Col1, Col2)declare @n int Set @n = 3 select @d = count(*) from ( select col1, col2, xyz from ( Select a.col1, a.col2, (Select count(1) From #s as x Where x.col1 = A.col1 and x.col2 <= a.col2 ) as xyz From #s as A) as d Where xyz <= @n -- Order By col1, col2) as eselect datediff(ms, @dt, current_timestamp) / 1000.0drop table #s[/code]Peter LarssonHelsingborg, Sweden |
 |
|
|
|
|
|
|
|