Insert top 253 values where value in select distinct tradernames
-
07-02-2021 - |
Question
I am trying to insert top 253 values for each trader from a temp traders table into temp results table.
I am using following code to do it.
CREATE TABLE #trad ( Trad varchar(50))
IF @trad is not null
INSERT INTO #Trad
SELECT DISTINCT * FROM dbo.Split(@trad,',') -- split will have traders seperated by commas
ELSE INSERT INTO #Traders
Select distinct Trader from TraderMap tm
where traderorgroup = 'trader'
CREATE TABLE #result
(port VARCHAR(50),portdate DATE,P MONEY,V_95 MONEY,
V_99 MONEY,VLimit MONEY,V_90 MONEY,H_99 MONEY,
H_975 MONEY,H_95 MONEY,H_90 MONEY,H_80 MONEY,dCnt
INT,Trad varchar(100))
DECLARE @traderlist AS Varchar(100)
DECLARE traderlist CURSOR FOR
SELECT DISTINCT Traders FROM #traders
OPEN traderlist
FETCH next FROM traderlist INTO @traderlist
WHILE @@FETCH_STATUS = 0
BEGIN
INSERT INTO #result (port, portdate, P, V_95, V_99, VLimit,
dCnt,Trad)
SELECT TOP 253 pl.Port,pl.Portdate,pl.dtd_P
PL,var.V_95,var.V_99, sum(gu.Guid * -1) VLimit,
Row_number() OVER(partition by pl.TradName ORDER BY Portdate DESC)
dCnt,pl.TradName
FROM Trad_PL pl INNER JOIN rep_tab var
ON pl.Portdate = var.V_Date
AND pl.Port = var.Port
AND pl.TradName = var.Trad
INNER JOIN Trad_Guid gui
ON pl.Port = gui.Port
AND pl.TradName = gui.Trad
WHERE pl.Portdate <= @portdate
AND pl.Port = CASE WHEN @port = 'Her' THEN 'Herport' ELSE
@port END
AND pl.ONA = 'Act'
AND pl.TradName = @tradlist
AND var.PType = '0Trad'
group by
pl.TradName,pl.Port,pl.Portdate,pl.dtd_P,var.V_95,var.V_99
ORDER BY Portdate DESC
FETCH next FROM tradlist INTO @tradlist
END
CLOSE tradlist
DEALLOCATE tradlist
This code runs for hours. Is there any efficient way to get top 253 rows for each trad from Trad_PL and rep_tab.
Solution
In general if you have a cursor that's your first place to look for performance issues. It probably works great if you have 10 traders, not so well if you have 10,000.
Try this.
INSERT INTO #result (port, portdate, P, V_95, V_99, VLimit, dCnt,Trad)
SELECT pl.Port,pl.Portdate,pl.dtd_P
PL,var.V_95,var.V_99, sum(gu.Guid * -1) VLimit,
Row_number() OVER(partition by pl.TradName ORDER BY Portdate DESC)
dCnt,pl.TradName
FROM Trad_PL pl
INNER JOIN #Traders
ON #Traders.Traders = pl.TradName
INNER JOIN rep_tab var
ON pl.Portdate = var.V_Date
AND pl.Port = var.Port
AND pl.TradName = var.Trad
INNER JOIN Trad_Guid gui
ON pl.Port = gui.Port
AND pl.TradName = gui.Trad
WHERE pl.Portdate <= @portdate
AND pl.Port = CASE WHEN @port = 'Her' THEN 'Herport' ELSE @port END
AND pl.ONA = 'Act'
AND var.PType = '0Trad'
AND dCnt <= 253
group by
pl.TradName,pl.Port,pl.Portdate,pl.dtd_P,var.V_95,var.V_99
ORDER BY Portdate DESC
I removed the where clause that hit @tradlist and just joined to your temp table (which was already created from a distinct list of traders so no worries there). I also eliminated the TOP 253. You are already creating a row number with your dCnt field so I just added an entry to the WHERE clause where dCnt <= 253.
If you are still having performance problems I'd make sure you have indexes related to each of your joins and take a look at the query plan. Performance tuning in general is a big subject but you could do worse than buying a copy of Grant Fritchey's Execution Plan book. There is even a free ebook copy.
Last but not least, completely away from your actual question, formatting is your friend when posting pieces of code. You are far more likely to get positive responses (and answers) if your code is easier to read. If you look, the piece of code I am posting is formatted to make it easier to read. You certainly don't have to use this particular layout, formatting can be a very personal thing, but something other than all of the code down the left hand side of the screen is usually helpful.