September 7, 2007 at 2:42 am
Hi there.
I have a stored procedure that calls data from one of our tables based on a certain parameter (yearmonth) and then creates and inserts that data into a temporary table using row_number() to order the data by amount, with the highest amount being the first row in the table.
Then from that table there is a select statement that requires a parameter based on user input (their username/alias) and returns a result set.
Now here is where the tricky part comes in:
I want to be able to pull the users data based on their query (username/alias) as well as 3 rows before and 3 rows after.
To make it trickier, if the user query returns the first row, then I want it only to show 3 rows after as there are no rows before.
Is that possible using functions or Transact-SQL or would I have to code those requirements using my ASP function that shows the users results...
Thanks.
Byron
September 7, 2007 at 4:29 am
Byron
Please will you give us the CREATE TABLE statement for your temporary table.
Also, please have a read of this - it'll help others to help you as quickly as they can.
http://www.aspfaq.com/etiquette.asp?id=5006
Thanks
John
September 7, 2007 at 4:41 am
Hi John.
I was able to come up with something that works exactly the way I need, but I think that it may be very server intensive if many people are doing the same queries together.
If a person is in first place it only shows 3 results that are below them, as their is nothing above, but if the person is in say 10th, it will return 3 people before (7,8,9) and 3 people after (11,12,13).
It also adds that the person that is doing the query gets marked as the person who does the query, for output purposes.
Can I maybe lighten the code a little, or this how its meant to be done. Thanks
Here is the stored procedure
======================================================
alter proc usp_MPVRankByAlias
@CurrentMonth int,
@PlayerAlias varchar(50)
as
set nocount on
-- Create Temp Table to Store Data based on the first param (@CurrentMonth)
create table #tblMPVAliasByRank(
Rank int,
Alias varchar(50),
Country varchar(25),
Yearmonth int,
PrizeAmount decimal(10,2)
)
-- Create Temp Table to store results based on T-SQL and second param (@PlayerAlias)
create table #RankResults(
Rank int,
Alias varchar(50),
Country varchar(25),
Yearmonth int,
PrizeAmount decimal(10,2),
Requester varchar(50)
)
-- Insert data ordered by PrizeAmount for the current month
insert into #tblMPVAliasByRank (Rank, Alias, Country, Yearmonth, PrizeAmount)
select ROW_NUMBER() over (order by PrizeAmount desc) as Rank, Alias, Country, Yearmonth, PrizeAmount
from tblMPVLeaderBoard where Yearmonth = @CurrentMonth
-- Insert results from the person who requested their ranking and mark as requester
insert into #RankResults (Rank, Alias, Country, Yearmonth, PrizeAmount)
select * from #tblMPVAliasByRank where Alias = @PlayerAlias
update #RankResults set Requester = @PlayerAlias where Alias = @PlayerAlias
-- Start 3 Prior Rows
insert into #RankResults (Rank, Alias, Country, Yearmonth, PrizeAmount)
select * from #tblMPVAliasByRank where Rank =
(Select Rank from #tblMPVAliasByRank where Alias = @PlayerAlias)-1
insert into #RankResults (Rank, Alias, Country, Yearmonth, PrizeAmount)
select * from #tblMPVAliasByRank where Rank =
(Select Rank from #tblMPVAliasByRank where Alias = @PlayerAlias)-2
insert into #RankResults (Rank, Alias, Country, Yearmonth, PrizeAmount)
select * from #tblMPVAliasByRank where Rank =
(Select Rank from #tblMPVAliasByRank where Alias = @PlayerAlias)-3
-- Start 3 After Rows
insert into #RankResults (Rank, Alias, Country, Yearmonth, PrizeAmount)
select * from #tblMPVAliasByRank where Rank =
(Select Rank from #tblMPVAliasByRank where Alias = @PlayerAlias)+1
insert into #RankResults (Rank, Alias, Country, Yearmonth, PrizeAmount)
select * from #tblMPVAliasByRank where Rank =
(Select Rank from #tblMPVAliasByRank where Alias = @PlayerAlias)+2
insert into #RankResults (Rank, Alias, Country, Yearmonth, PrizeAmount)
select * from #tblMPVAliasByRank where Rank =
(Select Rank from #tblMPVAliasByRank where Alias = @PlayerAlias)+3
select * from #RankResults order by Rank
September 7, 2007 at 4:49 am
tblMPVLeaderBoard - is the main table that the data is taken from
and the create statement for that is
create table tblMPVLeaderBoard(
LeaderBoardID int,
Yearmonth varchar(50),
Alias nvarchar(40),
Country varchar(50) int,
PrizeAmount decimal(10,2)
)
and the insert statement for 10 results
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(1,200705,'8ell','USA',1.50)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(2,200705,'aaronp85','USA',34.75)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(3,200705,'abbydabby','Canada',2.00)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(4,200705,'AsianQueen4o8','USA',10.00)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(5,200705,'auntyflash','USA',10.00)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(6,200705,'Babonator','USA',26.25)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(7,200705,'bbjoe','United Kingdom',3.00)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(8,200705,'blaire20037','Canada',41.25)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(9,200705,'blutopaz','USA',85.00)
INSERT INTO [tblMPVLeaderboard] ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(10,200705,'Cannibal_Holocaust','USA',18.00)
September 7, 2007 at 5:10 am
So this is on SQL2005 ?
Try this new CTE :
-- replaced your persistent table to #temptb just for testing
create
table #tblMPVLeaderBoard(
LeaderBoardID int,
Yearmonth INT , --varchar(50),
Alias nvarchar(40),
Country VARCHAR(50) ,
PrizeAmount decimal(10,2)
)
--and the insert statement for 10 results
SET
NOCOUNT on
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(1,200705,'8ell','USA',1.50)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(2,200705,'aaronp85','USA',34.75)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(3,200705,'abbydabby','Canada',2.00)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(4,200705,'AsianQueen4o8','USA',10.00)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(5,200705,'auntyflash','USA',10.00)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(6,200705,'Babonator','USA',26.25)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(7,200705,'bbjoe','United Kingdom',3.00)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(8,200705,'blaire20037','Canada',41.25)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(9,200705,'blutopaz','USA',85.00)
INSERT
INTO #tblMPVLeaderBoard ([LeaderBoardID],[Yearmonth],[Alias],[Country],[PrizeAmount])VALUES(10,200705,'Cannibal_Holocaust','USA',18.00)
SET
NOCOUNT OFF
DECLARE
@CurrentMonth INT
DECLARE
@PlayerAlias NVARCHAR(40)
SET
@CurrentMonth = 200705
SET
@PlayerAlias = N'AsianQueen4o8'
;
with cteMPVAliasByRank (Ranking, Alias, Country, Yearmonth, PrizeAmount)
as (select ROW_NUMBER() over (order by PrizeAmount desc) , Alias, Country, Yearmonth, PrizeAmount
from #tblMPVLeaderBoard where Yearmonth = @CurrentMonth )
SELECT M.*
FROM cteMPVAliasByRank M
INNER JOIN cteMPVAliasByRank PA
ON PA.Alias = @PlayerAlias
AND M.Ranking BETWEEN PA.Ranking - 3 AND PA.Ranking + 3 ;
![]()
ps. update the query innerjoin part in stead of the double where-clause
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data and code to get the best help
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
September 7, 2007 at 5:33 am
excuse my ignorance... I am new to SQL Server.
Yes this is SQL Server 2005.
Can CTE's be used within a Stored Procedure? It works fine within SQL Server Management Studio if I do a query on your code directly, just trying something based on way you have given me. Thanks!
September 7, 2007 at 6:12 am
Can CTE's be used within a Stored Procedure?
Yes they can !
CTE's are new with Tsql in SQL2005. Search BOL or SSC
for more info.
Just take care to start your cte definition with a ;
The with statement needs to be preceded with a semicolon !
(in fact the preceding statement needs to be ending with one
)
but it doesn't hurt to have two, so start your with-clause with a semicolon.
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data and code to get the best help
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
September 7, 2007 at 6:14 am
Thanks for the heads up on CTE... Much easier than my previous query and much faster when i tested it on the real table.
Here is the new stored procedure which is cut down from 65 lines to 16.
alter proc usp_MPVRankByAlias
@CurrentMonth int,
@PlayerAlias varchar(50)
as
with cteAliasByRank (Rank, Alias, Country, Yearmonth, PrizeAmount) as
(
select ROW_NUMBER() over (order by PrizeAmount desc) as
Rank, Alias, Country, Yearmonth, PrizeAmount
from tblMPVLeaderBoard where Yearmonth = @CurrentMonth
)
select * from cteAliasByRank where
Rank >= (select min(Rank) - 3 from cteAliasByRank where alias = @PlayerAlias)
and
Rank <= (select min(Rank) + 3 from cteAliasByRank where alias = @PlayerAlias)
ALZDBA you are a legend. Thanks. I knew there was a quicker way just not used to all these transactional functions that are built into SQL Server 2005.
September 7, 2007 at 6:32 am
Because of the contraints you have in the CTE, you might not even need MIN in the sub-selects.
--Jeff Moden
Change is inevitable... Change for the better is not.
September 7, 2007 at 6:34 am
btw the most common use of CTE's is as a replacement for nested table expressions.
In many cases in join operations, CTE's will outperform repeated nested table expressions.
Check BOL or SSC
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data and code to get the best help
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
September 7, 2007 at 6:40 am
indeed, that's a little confusing flaw in my code part. ![]()
As you can see my first code post, I'd updated it before you replied.
Just for completeness this should be the query :
;with cteMPVAliasByRank (Ranking, Alias, Country, Yearmonth, PrizeAmount)
as (select ROW_NUMBER() over (order by PrizeAmount desc) , Alias, Country, Yearmonth, PrizeAmount
from #tblMPVLeaderBoard where Yearmonth = @CurrentMonth )
SELECT M.*
FROM cteMPVAliasByRank M
INNER JOIN cteMPVAliasByRank PA
ON PA.Alias = @PlayerAlias
AND M.Ranking BETWEEN PA.Ranking - 3 AND PA.Ranking + 3 ;
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data and code to get the best help
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
September 7, 2007 at 6:43 am
@ Jeff: Thanks, I have just tested it and it works without the min statement.
@ ALZDBA: I will definitely look into BOL and SSC, but I have one last thing before I go.
In my old SP I had an extra column called Requester, so that I could map who had done the request (for presentation) but if I try and add it to the CTE statement I get an error because we are populating the CTE based on a select statement and there are less columns in that select statements Table.
Is there a way to add that column and add the contents within that same CTE?
September 7, 2007 at 7:56 am
No problem, just add the highlighted
;with cteMPVAliasByRank (Ranking, Alias, Country, Yearmonth, PrizeAmount)
as (select ROW_NUMBER() over (order by PrizeAmount desc) , Alias, Country, Yearmonth, PrizeAmount
from #tblMPVLeaderBoard where Yearmonth = @CurrentMonth )
SELECT M.*, cast(@PlayerAlias as varchar(50) ) as Requester
FROM cteMPVAliasByRank M
INNER JOIN cteMPVAliasByRank PA
ON PA.Alias = @PlayerAlias
AND M.Ranking BETWEEN PA.Ranking - 3 AND PA.Ranking + 3 ;
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data and code to get the best help
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
September 7, 2007 at 8:03 am
Heh... sorry... you post faster than I do ![]()
--Jeff Moden
Change is inevitable... Change for the better is not.
September 7, 2007 at 8:12 am
I try to write slow, for those who cannot read fast ![]()
![]()
Seriously, today has been one of the few days in months that I've been able to perform some research on the web, also giving me time to reply frequent.
![]()
Johan
Learn to play, play to learn !
Dont drive faster than your guardian angel can fly ...
but keeping both feet on the ground wont get you anywhere :w00t:
- How to post Performance Problems
- How to post data and code to get the best help
- How to prevent a sore throat after hours of presenting ppt
press F1 for solution, press shift+F1 for urgent solution 😀
Need a bit of Powershell? How about this
Who am I ? Sometimes this is me but most of the time this is me
Viewing 15 posts - 1 through 15 (of 20 total)
You must be logged in to reply to this topic. Login to reply