This type of QUERY is the one that supports more use cases. It's performance is not as good as it's CTE counterparts but allows some use cases that CTE versions don't allow. It supports its use against tables with millions of records and with queries that has JOINs and a ton of filtering parameters.
It is divided in three parts. The first part is the temporal table creation. Two temporal tables are needed, one for filtering and the other for ordering. The ordering table is also used to retrieve a page of rows. Once created the temporal tables the second part fills the first temporal table with records that comply certain criteria (filtering them). To do this, a dynamic query is built in a string, in the WHERE part only are informed the filter parameters that actually have a value. This way although 19 filter parameters are used there's no performance penalty.
Once this first table is full of records is time to order them, so a ROW_NUMBER function is used in the third and last part of the query. It works well because in the first table a DISTINCT is used to avoid duplicate rows. In the WHERE part of this second temporal table a page of rows is obtained.
A stored procedure this long is a bit slow with tables that have 1.6 million of rows, and in a not very good server it can last from 16 to 26 seconds. In order to reduce this time a cache is needed but this will be explained in the C# post of clsData.
As usual the full code of the SP:
USE [DI_REAL]
GO
/****** Object: StoredProcedure [dbo].[DI_EXP_EXPEDIENTARXIU_QUERY] Script Date: 11/27/2013 17:09:53 ******/SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTERPROCEDURE [dbo].[DI_EXP_EXPEDIENTARXIU_QUERY]
@pPK_ExpedientArxiu int,
@pTitol varchar(255),
@pExped_I varchar(50),
@pAny_Obertura int,
@pExped_F varchar(50),
@pFK_LLocDiposit int,
@pFK_Classificacio int,
@pFK_Destruccio int,
@pFK_Procedencia int,
@pFK_Especifica int,
@pAny_Tancament int,
@pFK_Transferencia int,
@pFK_Estat int,
@pFK_Arxiu int,
@pFK_TAAD int,
@pFK_Uniforme int,
@pFK_Capsa int,
@pAny_OberturaMesGran int,
@pAny_TancamentMenor int,
@pCapsa varchar(30),
@pSortColumn NVARCHAR(50) = null,
@pPageSize INT = 10,
@pPageNum INT = 1
ASBEGINSETNOCOUNTON;
--Creation of the first table, used for filteringIF OBJECT_ID('tempdb..#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre') IS NOT NULLDROPTABLE #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre
CREATETABLE #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre
(
PK_ExpedientArxiu int,
FK_Procedencia int,
FK_Classificacio int,
FK_Uniforme int,
FK_Especifica int,
FK_LLocDiposit int,
FK_Estat int,
Titol varchar(255),
Exped_I varchar(50),
Exped_F varchar(50),
Any_Obertura int,
Any_Tancament int,
U_Instal_I varchar(30),
U_Instal_F varchar(30),
Volum int,
Adreca varchar(250),
SigTop_I varchar(30),
SigTop_F varchar(30),
Codi_TC nvarchar(5),
Uniforme_TC nvarchar(5),
Especifica_TC nvarchar(10),
Codi_Procedencia nvarchar(5),
N_NivellP nvarchar(200),
Diposit nvarchar(200),
Capsa varchar(30),
Sigla varchar(6),
CapsaHist varchar(50),
Estat varchar(50)
)
--Creation of the second temporal table, the one used in sortingIF OBJECT_ID('tempdb..#TempTBLDI_EXP_EXPEDIENTARXIU_Ordenacio') IS NOT NULLDROPTABLE #TempTBLDI_EXP_EXPEDIENTARXIU_Ordenacio
CREATETABLE #TempTBLDI_EXP_EXPEDIENTARXIU_Ordenacio
(
NumRegs bigint,
RowNumber bigint,
PK_ExpedientArxiu int,
FK_Procedencia int,
FK_Classificacio int,
FK_Uniforme int,
FK_Especifica int,
FK_LLocDiposit int,
FK_Estat int,
Titol varchar(255),
Exped_I varchar(50),
Exped_F varchar(50),
Any_Obertura int,
Any_Tancament int,
U_Instal_I varchar(30),
U_Instal_F varchar(30),
Volum int,
Adreca varchar(250),
SigTop_I varchar(30),
SigTop_F varchar(30),
Codi_TC nvarchar(5),
Uniforme_TC nvarchar(5),
Especifica_TC nvarchar(10),
Codi_Procedencia nvarchar(5),
N_NivellP nvarchar(200),
Diposit nvarchar(200),
Capsa varchar(30),
Sigla varchar(6),
CapsaHist varchar(50),
Estat varchar(50)
)
DECLARE @strSQL nvarchar(MAX)
DECLARE @strPARAMS nvarchar(MAX)
--First query to fill the table with filtered resultsSET @strSQL = 'INSERT INTO #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre
SELECT DISTINCT dbo.DI_EXP_EXPEDIENTARXIU.PK_ExpedientArxiu,
dbo.DI_EXP_EXPEDIENTARXIU.FK_Procedencia,
dbo.DI_EXP_EXPEDIENTARXIU.FK_Classificacio,
dbo.DI_EXP_EXPEDIENTARXIU.FK_Uniforme,
dbo.DI_EXP_EXPEDIENTARXIU.FK_Especifica,
dbo.DI_EXP_EXPEDIENTARXIU.FK_LLocDiposit,
dbo.DI_EXP_EXPEDIENTARXIU.FK_Estat,
dbo.DI_EXP_EXPEDIENTARXIU.Titol,
dbo.DI_EXP_EXPEDIENTARXIU.Exped_I,
dbo.DI_EXP_EXPEDIENTARXIU.Exped_F,
dbo.DI_EXP_EXPEDIENTARXIU.Any_Obertura,
dbo.DI_EXP_EXPEDIENTARXIU.Any_Tancament,
dbo.DI_EXP_EXPEDIENTARXIU.U_Instal_I,
dbo.DI_EXP_EXPEDIENTARXIU.U_Instal_F,
dbo.DI_EXP_EXPEDIENTARXIU.Volum,
dbo.DI_EXP_EXPEDIENTARXIU.Adreca,
dbo.DI_EXP_EXPEDIENTARXIU.SigTop_I,
dbo.DI_EXP_EXPEDIENTARXIU.SigTop_F,
dbo.DI_EXP_CLASSIFICACIO.Codi_TC,
dbo.DI_EXP_UNIFORME.Uniforme_TC,
dbo.DI_EXP_ESPECIFICA.Especifica_TC,
dbo.DI_EXP_PROCEDENCIA.Codi_TC AS Codi_Procedencia,
dbo.DI_EXP_PROCEDENCIA.N_NivellP,
dbo.DI_EXP_LLOCDIPOSIT.Nom AS Diposit,
dbo.DI_EXP_CAPSES.Capsa,
dbo.DI_EXP_LLOCDIPOSIT.Sigla,
dbo.DI_EXP_EXPEDIENTARXIU.CapsaHist,
dbo.DI_EXP_ESTAT.Nom AS Estat
FROM DI_EXP_EXPEDIENTARXIU INNER JOIN DI_EXP_CLASSIFICACIO
ON DI_EXP_EXPEDIENTARXIU.FK_Classificacio=DI_EXP_CLASSIFICACIO.PK_Classificacio
LEFT OUTER JOIN DI_EXP_ESPECIFICA
ON DI_EXP_EXPEDIENTARXIU.FK_Especifica=DI_EXP_ESPECIFICA.PK_Especifica
LEFT OUTER JOIN DI_EXP_UNIFORME
ON DI_EXP_EXPEDIENTARXIU.FK_Uniforme=DI_EXP_UNIFORME.PK_Uniforme
INNER JOIN DI_EXP_PROCEDENCIA
ON DI_EXP_EXPEDIENTARXIU.FK_Procedencia=DI_EXP_PROCEDENCIA.PK_Procedencia
LEFT OUTER JOIN DI_EXP_TAAD_REL
ON DI_EXP_CLASSIFICACIO.PK_Classificacio=DI_EXP_TAAD_REL.FK_Classificacio
LEFT OUTER JOIN DI_EXP_CAPSA_EXPEDIENT
ON DI_EXP_EXPEDIENTARXIU.PK_ExpedientArxiu=DI_EXP_CAPSA_EXPEDIENT.FK_ExpedientArxiu
LEFT OUTER JOIN DI_EXP_CAPSES
ON DI_EXP_CAPSA_EXPEDIENT.FK_Capsa=DI_EXP_CAPSES.PK_Capsa
LEFT OUTER JOIN DI_EXP_SIGTOP ON DI_EXP_CAPSES.PK_Capsa=DI_EXP_SIGTOP.FK_Capsa
LEFT OUTER JOIN DI_EXP_LLOCDIPOSIT
ON DI_EXP_SIGTOP.FK_LlocDiposit=DI_EXP_LLOCDIPOSIT.PK_LLocDiposit
INNER JOIN DI_EXP_ESTAT ON DI_EXP_EXPEDIENTARXIU.FK_Estat=DI_EXP_ESTAT.PK_Estat
WHERE 1=1 '--Dynamic WHERE--There's a ton of possible filtersIF @pPK_ExpedientArxiu IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.PK_ExpedientArxiu=@lPK_ExpedientArxiu'ENDIF @pTitol IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.Titol LIKE @lTitol + ''%'''ENDIF @pExped_I IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.Exped_I LIKE @lExped_I + ''%'''ENDIF @pAny_Obertura IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.Any_Obertura = @lAny_Obertura'ENDIF @pExped_F IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.Exped_F LIKE @lExped_F + ''%'''ENDIF @pFK_LLocDiposit IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_SIGTOP.FK_LLocDiposit = @lFK_LLocDiposit'ENDIF @pFK_Classificacio IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Classificacio = @lFK_Classificacio'ENDIF @pFK_Destruccio IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Destruccio = @lFK_Destruccio'ENDIF @pFK_Procedencia IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Procedencia = @lFK_Procedencia'ENDIF @pFK_Especifica IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Especifica = @lFK_Especifica'ENDIF @pAny_Tancament IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.Any_Tancament = @lAny_Tancament'ENDIF @pFK_Transferencia IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Transferencia = @lFK_Transferencia'ENDIF @pFK_Estat IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Estat = @lFK_Estat'ENDIF @pFK_Arxiu IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Arxiu = @lFK_Arxiu'ENDIF @pFK_TAAD IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_TAAD_REL.FK_TAAD = @lFK_TAAD'ENDIF @pFK_Uniforme IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.FK_Uniforme = @lFK_Uniforme'ENDIF @pFK_Capsa IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_CAPSA_EXPEDIENT.FK_Capsa = @lFK_Capsa'ENDIF @pAny_OberturaMesGran IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.Any_Obertura >= @lAny_OberturaMesGran'ENDIF @pAny_TancamentMenor IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_EXPEDIENTARXIU.Any_Tancament <= @lAny_TancamentMenor'ENDIF @pCapsa IS NOT NULLBEGINSET @strSQL = @strSQL + ' AND dbo.DI_EXP_CAPSES.Capsa LIKE @lCapsa + ''%'''END-- Construction of the parametersSET @strPARAMS = '@lPK_ExpedientArxiu int,
@lTitol varchar(255),
@lExped_I varchar(50),
@lAny_Obertura int,
@lExped_F varchar(50),
@lFK_LLocDiposit int,
@lFK_Classificacio int,
@lFK_Destruccio int,
@lFK_Procedencia int,
@lFK_Especifica int,
@lAny_Tancament int,
@lFK_Transferencia int,
@lFK_Estat int,
@lFK_Arxiu int,
@lFK_TAAD int,
@lFK_Uniforme int,
@lFK_Capsa int,
@lAny_OberturaMesGran int,
@lAny_TancamentMenor int,
@lCapsa varchar(30)'--Execution with parameter informedEXECUTE sp_executesql @strSQL, @strPARAMS,
@pPK_ExpedientArxiu,
@pTitol,
@pExped_I,
@pAny_Obertura,
@pExped_F,
@pFK_LLocDiposit,
@pFK_Classificacio,
@pFK_Destruccio,
@pFK_Procedencia,
@pFK_Especifica,
@pAny_Tancament,
@pFK_Transferencia,
@pFK_Estat,
@pFK_Arxiu,
@pFK_TAAD,
@pFK_Uniforme,
@pFK_Capsa,
@pAny_OberturaMesGran,
@pAny_TancamentMenor,
@pCapsa;
--Insert filtered data applying a parametrized sortINSERTINTO #TempTBLDI_EXP_EXPEDIENTARXIU_Ordenacio
SELECT
COUNT(*) OVER () AS NumRegs,
ROW_NUMBER()
OVER(ORDERBYCASEWHEN @pSortColumn = 'PK_ExpedientArxiuASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.PK_ExpedientArxiu ENDASC,
CASEWHEN @pSortColumn = 'PK_ExpedientArxiuDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.PK_ExpedientArxiu ENDDESC,
CASEWHEN @pSortColumn = 'FK_ProcedenciaASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Procedencia ENDASC,
CASEWHEN @pSortColumn = 'FK_ProcedenciaDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Procedencia ENDDESC,
CASEWHEN @pSortColumn = 'FK_ClassificacioASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Classificacio ENDASC,
CASEWHEN @pSortColumn = 'FK_ClassificacioDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Classificacio ENDDESC,
CASEWHEN @pSortColumn = 'FK_UniformeASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Uniforme ENDASC,
CASEWHEN @pSortColumn = 'FK_UniformeDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Uniforme ENDDESC,
CASEWHEN @pSortColumn = 'FK_EspecificaASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Especifica ENDASC,
CASEWHEN @pSortColumn = 'FK_EspecificaDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Especifica ENDDESC,
CASEWHEN @pSortColumn = 'TitolASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Titol ENDASC,
CASEWHEN @pSortColumn = 'TitolDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Titol ENDDESC,
CASEWHEN @pSortColumn = 'Exped_IASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Exped_I ENDASC,
CASEWHEN @pSortColumn = 'Exped_IDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Exped_I ENDDESC,
CASEWHEN @pSortColumn = 'Any_OberturaASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Any_Obertura ENDASC,
CASEWHEN @pSortColumn = 'Any_OberturaDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Any_Obertura ENDDESC,
CASEWHEN @pSortColumn = 'Any_TancamentASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Any_Tancament ENDASC,
CASEWHEN @pSortColumn = 'Any_TancamentDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Any_Tancament ENDDESC,
CASEWHEN @pSortColumn = 'U_Instal_IASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.U_Instal_I ENDASC,
CASEWHEN @pSortColumn = 'U_Instal_IDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.U_Instal_I ENDDESC,
CASEWHEN @pSortColumn = 'U_Instal_FASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.U_Instal_F ENDASC,
CASEWHEN @pSortColumn = 'U_Instal_FDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.U_Instal_F ENDDESC,
CASEWHEN @pSortColumn = 'SigTop_IASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.SigTop_I ENDASC,
CASEWHEN @pSortColumn = 'SigTop_IDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.SigTop_I ENDDESC,
CASEWHEN @pSortColumn = 'SigTop_FASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.SigTop_F ENDASC,
CASEWHEN @pSortColumn = 'SigTop_FDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.SigTop_F ENDDESC,
CASEWHEN @pSortColumn = 'CapsaASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Capsa ENDASC,
CASEWHEN @pSortColumn = 'CapsaDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Capsa ENDDESC,
CASEWHEN @pSortColumn = 'SiglaASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Sigla ENDASC,
CASEWHEN @pSortColumn = 'SiglaDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Sigla ENDDESC,
CASEWHEN @pSortColumn = 'CapsaHistASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.CapsaHist ENDASC,
CASEWHEN @pSortColumn = 'CapsaHistDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.CapsaHist ENDDESC,
CASEWHEN @pSortColumn = 'EstatASC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Estat ENDASC,
CASEWHEN @pSortColumn = 'EstatDESC'THEN #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Estat ENDDESC
)
AS RowNumber,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.PK_ExpedientArxiu,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Procedencia,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Classificacio,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Uniforme,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Especifica,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_LLocDiposit,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.FK_Estat,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Titol,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Exped_I,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Exped_F,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Any_Obertura,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Any_Tancament,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.U_Instal_I,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.U_Instal_F,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Volum,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Adreca,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.SigTop_I,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.SigTop_F,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Codi_TC,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Uniforme_TC,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Especifica_TC,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Codi_Procedencia,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.N_NivellP,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Diposit,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Capsa,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Sigla,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.CapsaHist,
#TempTBLDI_EXP_EXPEDIENTARXIU_Filtre.Estat
FROM #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre
--Get the desired pageSELECT * FROM #TempTBLDI_EXP_EXPEDIENTARXIU_Ordenacio
WHERE RowNumber >= (@pPageSize * @pPageNum) - (@pPageSize -1) AND RowNumber <= @pPageSize * @pPageNum
ORDERBY RowNumber
--Final cleaningDROPTABLE #TempTBLDI_EXP_EXPEDIENTARXIU_Filtre
DROPTABLE #TempTBLDI_EXP_EXPEDIENTARXIU_Ordenacio
END
#12/03/2014 16:57 Programming SQLServer Author: Alex Canalda