Quantcast
Channel: Transact-SQL forum
Viewing all articles
Browse latest Browse all 23857

More efficient way to do this SQL Procedure

$
0
0

I am creating a stored procedure that is used by another program.  The procedure is very slow for large databases, and I wanted to see if there are suggestions on making it faster.   Each entry in the database has a time stamp, which is not necessarily unique.  Some rows share the same time stamp.   I want to get a list of the distinct timestamps for which a list of conditions is true for that time stamp (across multiple rows).   I first select data from the database data to populate a @searchTbl by selecting rows in the table that have either a specific User, Var3, and/or Time (if these are sent to the procedure and so are not NULL).  If the user does not send a specific time (If NULL), I get the latest entries for each unique combination of certain variables (Var4, Var1, Var2, Var3).  I then eliminate rows from the @searchTbl by selecting terms from a conditions table (@condTbl) to create a new select statement.  For each recursive loop, I put the new selection into a @loopTbl, then delete from the @searchTbl, then populate the @searchTbl with the @loopTbl data, then delete the @loopTbl data (I know this is embarrassingly inefficient).

Is there a way to accomplish all of this more efficiently without using the @searchTbl and/or @loopTbl?   I think this might be why it's so slow, because I have to put nearly the whole database into the @searchTbl to begin. 

EDIT NOTE:  SEE MY RESPONSE DOWN THE PAGE FOR THE STORED PROCEDURE DDL


The code to create the table types is listed below the procedure code:


Gina


DECLARE @ProjectTable nvarchar(128)
SET @ProjectTable = 'RIProj_HCT'
DECLARE @CondTbl conditions_tbltype READONLY
DECLARE @UserName nvarchar(255) = NULL
DECLARE @eTime datetime = NULL 
DECLARE @Var3 nvarchar(255) = NULL
DECLARE @SQL nvarchar(4000)
DECLARE @whereAdd nvarchar(4000)
DECLARE @Var4 nvarchar(255)
DECLARE @Var4Var3Time nvarchar(255)
DECLARE @Var1 nvarchar(255)
DECLARE @Var2 nvarchar(255)
DECLARE @CondSign nvarchar(30)
DECLARE @ValType nvarchar(255)
DECLARE @VarTxt nvarchar(4000)
DECLARE @VarNum float
DECLARE @c int
DECLARE @condCt int
SET @condCt = (SELECT count(*) FROM @CondTbl)
DECLARE @SearchTbl tempSearchTbl_tbltype
DECLARE @LoopTbl tempSearchTbl_tbltype
IF (object_id(@ProjectTable) is NULL)
           BEGIN
              RETURN
           END
              SET @whereAdd = ''
              IF @Var3 IS NOT NULL
                 BEGIN
                     SET @whereAdd =  @whereAdd + ' AND Var3 = @Var3'
                  END
              IF @UserName IS NOT NULL
                 BEGIN
                     SET @whereAdd = @whereAdd +' AND UserName = @UserName'
                     END
              IF @Time IS NOT NULL
                 BEGIN
                     SET @whereAdd = @whereAdd +' AND eTime = @eTime'
                 END
              ELSE
                 BEGIN
                     SET @whereAdd = @whereAdd +' AND NOT EXISTS (SELECT 1 FROM ' + @ProjectTable + ' WHERE
                     Var4 = p.Var4 AND Var1 = p.Var1 AND Var2 = p.Var2 AND
                     Var3 = p.Var3 AND Time > p.eTime)'
                 END
              SET @SQL = 'SELECT Var4, UserName, Var3, Var1, VarNum, VarTxt, NForm,
                                     Var2, eTime, Var4Var3Time FROM ' + @ProjectTable + ' p WHERE 1 = 1' + @whereAdd
              INSERT INTO @SearchTbl (Var4, UserName, Var3, Var1, VarNum, VarTxt, NForm, Var2, eTime,
                             Var4Var3Time)
                     EXEC sp_executesql @SQL,
                         N'@Var4 nvarchar(255), @UserName nvarchar(255), @ProjectTable nvarchar(255),
                           @Var3 nvarchar(255)',
                         @Var4, @UserName, @ProjectTable, @Var3
 ConditionLoop:
              IF @condCt >= 1
                 BEGIN
                     SET @c = 1
                     WHILE @c <= @condCt
                         BEGIN
                             SET @Var1 = (SELECT Var1 FROM @CondTbl WHERE cID = @c)
                             SET @Var2 = (SELECT Var2 FROM @CondTbl WHERE cID = @c)
                             SET @CondSign = (SELECT condSign FROM @CondTbl WHERE cID = @c)
                             SET @ValType = (SELECT ValType FROM @CondTbl WHERE cID = @c)
                             SET @VarTxt = (SELECT ValTxt FROM @CondTbl WHERE cID = @c)
                             SET @VarNum = (SELECT ValValue FROM @CondTbl WHERE cID = @c)
                             SET @SQL = 'SELECT * FROM @SearchTbl WHERE Var4 + CONVERT(VARCHAR(100), Time, 121) IN
                                     (SELECT Var4 + CONVERT(VARCHAR(100), Time, 121) AS TagTime FROM @SearchTbl'
                             SET @SQL = @SQL + ' WHERE Var1 = @Var1 AND Var2 = @Var2'
                             IF @ValType = 'Num'
                                 BEGIN
                                     SET @SQL = @SQL + ' AND VarNum ' + @CondSign + ' @VarNum'
                                 END
                             IF @ValType = 'Text'
                                 BEGIN
                                     IF @CondSign = 'LIKE'
                                         BEGIN
                                             SET @SQL = @SQL + ' AND VarTxt LIKE @VarTxt'
                                         END
                                     IF @CondSign = 'NOT LIKE'
                                         BEGIN
                                             SET @SQL = @SQL + ' AND NOT VarTxt LIKE @VarTxt'
                                         END
                                 END
                             SET @SQL = @SQL + ')'
                             DELETE FROM @LoopTbl
                             INSERT INTO @LoopTbl
                               EXEC sp_executesql @SQL,
                                 N'@SearchTbl tempSearchTbl_tbltype READONLY, @Var1 nvarchar(255), @Var2 nvarchar(255),
                                 @Time datetime, @Var3 nvarchar(255), @UserName nvarchar(255),
                                 @VarNum float, @VarTxt nvarchar(4000), @CondSign nvarchar(30)',
                                 @SearchTbl, @Var1, @Var2, @Time, @Var3,
                                 @UserName, @VarNum, @VarTxt, @CondSign
                             SET @c = @c + 1
                             DELETE FROM @SearchTbl
                             INSERT INTO @SearchTbl SELECT * FROM @LoopTbl
                         END
                 END
 FinalReturn:
     SELECT DISTINCT eTime FROM @SearchTbl
     RETURN

Code to create the table types used in this procedure:

CREATE TYPE conditions_tbltype AS TABLE (cID int, Var1 nvarchar(255) NOT NULL, Var2 nvarchar(255) NOT NULL, condSign nvarchar(255) NOT NULL, ValType nvarchar(255), ValTxt nvarchar(4000) NOT NULL, ValValue float)
CREATE TYPE tempSearchTbl_tbltype as TABLE (Var4 nvarchar(255), UserName nvarchar(255), Var3 nvarchar(255), Var1 nvarchar(255), VarNum float, VarTxt nvarchar(4000),NForm nvarchar(255), Var2 nvarchar(255), eTime datetime,
Var4Var3Time nvarchar(255))






Viewing all articles
Browse latest Browse all 23857

Trending Articles



<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>