Improve case statement in order clause - sql

I have the store sql
ALTER procedure [dbo].[TNNews_User_SearchBasic]
#Title nvarchar(400),
#CategoryId int,
#IsInterested int,
#IsHot int,
#IsTopCategory int,
#IsPublish int,
#PageSize int,
#PageIndex int,
#OrderBy varchar(20),
#PortalId int,
#LanguageId varchar(6)
as
DECLARE #EndTime DATETIME
DECLARE #StartTime DATETIME
SET #StartTime = GETDATE()
declare #tbCategory table(Id int)
DECLARE #StartRowIndex INT
IF #PageSize=0 SELECT #PageSize=count(*) FROM TNNews
IF(#PageIndex<0) SET #PageIndex=0
SET #StartRowIndex = #PageSize*(#PageIndex-1)+1
;WITH tmpCategory(Id, Name,ParentId,Level)
AS (
SELECT
e.Id,
e.Name,
e.ParentId,
1
FROM dbo.TNCategory AS e
WHERE
Id = #CategoryId or (#CategoryId='' and ParentId<=0)
UNION ALL
SELECT
e.Id,
e.Name,
e.ParentId,
Level + 1
FROM dbo.TNCategory AS e
JOIN tmpCategory AS d ON e.ParentId = d.Id
)
insert #tbCategory select Id from tmpCategory
;WITH tmpNews as
(
SELECT
a.Id,a.Title,a.Subject
,ROW_NUMBER() OVER (ORDER BY (Publisheddate) desc) as ThuTuBanGhi
FROM dbo.TNNews a
where 1 = 1
--and ( Title like '%'+#Title+'%')
and (#CategoryId = -1 or exists (select 0 from #tbCategory b where b.Id = a.CategoryId))
and (#IsInterested = -1 or IsIntrested = #IsInterested )
and (#IsHot = -1 or IsHot = #IsHot )
and (#IsTopCategory = -1 or IsTopCategory = #IsTopCategory )
and (#IsPublish = -1 or IsPublished = #IsPublish)
and PortalId=#PortalId
and LanguageId = #LanguageId
)
select *, (select COUNT(Id) from tmpNews) as 'TongSoBanGhi' from tmpNews
WHERE
ThuTuBanGhi BETWEEN (#StartRowIndex) AND (#StartRowIndex + #PageSize-1)
SET #EndTime = GETDATE()
PRINT 'StartTime = ' + CONVERT(VARCHAR(30),#StartTime,121)
PRINT ' EndTime = ' + CONVERT(VARCHAR(30),#EndTime,121)
PRINT ' Duration = ' + STR(DATEDIFF(MILLISECOND,#StartTime,#EndTime)) + ' millisecond'
select STR(DATEDIFF(MILLISECOND,#StartTime,#EndTime))
After this store excute
EXEC [dbo].[TNNews_User_SearchBasic]
#Title='',
#CategoryId = '',
#IsInterested = -1,
#IsHot = -1,
#IsTopCategory = -1,
#IsPublish = -1,
#PageSize = 20,
#PageIndex = 1,
#OrderBy = '',
#PortalId = 0,
#LanguageId = N'vi-VN'
go
The time excute about "200ms". And I create a new store "TNNews_User_SearchBasic1" with some change.
.....
--,ROW_NUMBER() OVER (ORDER BY (Publisheddate) desc) as ThuTuBanGhi
,ROW_NUMBER() OVER (ORDER BY (case when #OrderBy='VIEW_COUNT' then ViewCount else PublishedDate end) desc) as ThuTuBanGhi
.....
and now the time excute this store
EXEC [dbo].[TNNews_User_SearchBasic1]
#Title='',
#CategoryId = '',
#IsInterested = -1,
#IsHot = -1,
#IsTopCategory = -1,
#IsPublish = -1,
#PageSize = 20,
#PageIndex = 1,
#OrderBy = '',
#PortalId = 0,
#LanguageId = N'vi-VN'
GO
about 900ms.
I don't understand why there is a change. Please help me improve these stores.
PS: I put example db at: http://anhquan22.tk/Portals/0/Videos/web.rar

Finished analysis the structure of your database. The part of the problem is hiding in the table structure.
I have prepared a backup for you. In it, I slightly modified scheme to improve performance and some normalize the table. You can download it from this link.
...to your question, I would do like this -
DECLARE #SQL NVARCHAR(1000)
SELECT #SQL = N'
;WITH tmpCategory (Id, Name, ParentId, [Level]) AS
(
SELECT
e.Id
, e.Name
, e.ParentId
, 1
FROM dbo.TNCategory e
WHERE Id = #CategoryId OR (#CategoryId = '''' AND ParentId <= 0)
UNION ALL
SELECT
e.Id
, e.Name
, e.ParentId
, [Level] + 1
FROM dbo.TNCategory e
JOIN tmpCategory d ON e.ParentId = d.Id
)
SELECT
a.Id
, ROW_NUMBER() OVER (ORDER BY ' +
CASE WHEN #OrderBy = 'VIEW_COUNT'
THEN 'ViewCount'
ELSE 'PublishedDate'
END +' DESC) AS ThuTuBanGhi
FROM dbo.TNNewsMain a
where PortalId = #PortalId
AND LanguageId = #LanguageId'
+ CASE WHEN #IsInterested != -1 THEN ' AND IsInterested = #IsInterested' ELSE '' END
+ CASE WHEN #IsHot != -1 THEN ' AND IsHot = #IsHot' ELSE '' END
+ CASE WHEN #IsTopCategory != -1 THEN ' AND IsTopCategory = #IsTopCategory' ELSE '' END
+ CASE WHEN #IsPublish != -1 THEN ' AND IsPublish = #IsPublish' ELSE '' END
+ CASE WHEN #CategoryId != -1 THEN '' ELSE ' AND EXISTS(SELECT 1 FROM tmpCategory b WHERE b.Id = a.CategoryId)' END
INSERT INTO #temp (Id, ThuTuBanGhi)
EXECUTE sp_executesql
#SQL
, N'#PortalId INT
, #LanguageId VARCHAR(6)
, #CategoryId INT
, #IsInterested INT
, #IsHot INT
, #IsTopCategory INT
, #IsPublish INT'
, #PortalId = #PortalId
, #LanguageId = #LanguageId
, #CategoryId = #CategoryId
, #IsInterested = #IsInterested
, #IsHot = #IsHot
, #IsTopCategory = #IsTopCategory
, #IsPublish = #IsPublish;
SELECT
d.Id
, tm.Title
, tm.[Subject]
, d.ThuTuBanGhi
, c.TongSoBanGhi
FROM (
SELECT t.Id
, t.ThuTuBanGhi
FROM #temp t
WHERE t.ThuTuBanGhi BETWEEN #StartRowIndex AND #StartRowIndex + #PageSize - 1
) d
JOIN TNNewsMain tm ON d.Id = tm.Id
CROSS JOIN (
SELECT TongSoBanGhi = (SELECT COUNT(1) FROM #temp)
) c

Related

How to replace where clause with a function and use it in stored procedures?

I have two stored procedures that they have the same where clause, one of them is use for pagination:
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetPagedFilteredPersonnels]
(
#SortField varchar(512),
#PageNo int,
#PageSize int,
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
DECLARE #OffsetRows INT = CASE WHEN #PageNo = 1 THEN 0 ELSE (#PageNo - 1) * #PageSize END;
DECLARE #TotalCount INT;
WITH Result AS(
SELECT
CASE
WHEN #SortField = N'[FullName]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName])
WHEN #SortField = N'[FullName] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[FullName] DESC)
WHEN #SortField = N'[WorkingPeriodTitle]' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year],workingPeriods.[Index])
WHEN #SortField = N'[WorkingPeriodTitle] DESC' THEN ROW_NUMBER() OVER (ORDER BY calcs.[Year] DESC,workingPeriods.[Index] DESC)
WHEN #SortField = N'[PersonnelNo]' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo])
WHEN #SortField = N'[PersonnelNo] DESC' THEN ROW_NUMBER() OVER (ORDER BY salaried.[PersonnelNo] DESC)
END AS [RowNumber],
calcs.[Guid],
calcs.[CalculationCommandGuid],
calcs.[SalariedGuid],
salaried.[PersonnelNo],
salaried.[FullName] AS [PersonnelFullName],
command.[Type] [CommandType],
salaried.[SalariedType],
workingPeriods.Title AS [WorkingPeriodTitle],
command.[MainYear] AS [Year],
command.[Approved],
command.[FinalApproved]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid] INNER JOIN
prs_workingPeriods workingPeriods ON workingPeriods.[Id] = command.[MainWorkingPeriodID]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
), TableForTotalCount AS (SELECT COUNT(*) As TotalCount FROM Result)
SELECT
(SELECT TOP 1 TotalCount FROM TableForTotalCount) AS TotalCount,
*
FROM Result
ORDER BY
[RowNumber]
OFFSET #OffsetRows ROWS
FETCH NEXT #PageSize ROWS ONLY
and another one supposed to return some Guids
ALTER PROCEDURE [dbo].[ret_PayrollCalculations_GetFilteredPersonnels]
(
#CalculationCommandType int,
#StartWorkingPeriodId int,
#StartYear int,
#EndWorkingPeriodId int,
#EndYear int,
#Status int,
#SalariedGuid uniqueidentifier,
#SalariedType int,
#OfficeNumber varchar(64),
#SalariedResultSetId int,
#Keyword nvarchar(2024),
#OperationalUnitIds [dbo].[ListOfID] READONLY
)
AS
DECLARE #AccessibleSalariedGuids [dbo].[ListOfGuid]
IF EXISTS (SELECT * FROM #OperationalUnitIDs)
BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT FeatureGuid FROM prs_OperationalUnitFeatures
WHERE
OperationalUnitID in (SELECT * FROM #OperationalUnitIDs) AND
FeatureFlag IN (2,4)
END
ELSE BEGIN
INSERT INTO #AccessibleSalariedGuids
SELECT [Guid] FROM ret_vwSalaried
END
SELECT
calcs.[Guid]
FROM
ret_PayrollCalculationCommands command INNER JOIN
ret_PayrollCalculations calcs ON calcs.[CalculationCommandGuid] = command.[Guid] INNER JOIN
ret_vwSalaried salaried ON calcs.[SalariedGuid] = salaried.[Guid]
WHERE
ISNULL(calcs.[MainCalculation],0) = 1 AND
ISNULL(command.[Deleted],0)=0 AND
(#Keyword = '' OR salaried.PersonnelNo = #Keyword OR salaried.FullName LIKE N'%' + #Keyword + '%' OR salaried.FullNameReversed LIKE N'%' + #Keyword + '%') AND
(ISNULL(#calculationCommandType, 0) = 0 OR command.[Type] = #calculationCommandType) AND
(ISNULL(#StartYear, 0) = 0 OR command.[MainYear] >= #StartYear) AND
(ISNULL(#StartWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] >= #StartWorkingPeriodId) AND
(ISNULL(#EndYear, 0) = 0 OR command.[MainYear] <= #EndYear) AND
(ISNULL(#EndWorkingPeriodId, 0) = 0 OR command.[MainWorkingPeriodID] <= #EndWorkingPeriodId) AND
(ISNULL(#Status, -1) = -1 OR command.[Approved] = #Status) AND
(ISNULL(#SalariedType, -1) = -1 OR salaried.[SalariedType] = #SalariedType) AND
(ISNULL(#SalariedGuid,'00000000-0000-0000-0000-000000000000') = '00000000-0000-0000-0000-000000000000' OR calcs.[SalariedGuid] = #SalariedGuid) AND
(#OfficeNumber IS NULL OR salaried.[OfficeNumber] LIKE '%'+#OfficeNumber+'%') AND
(ISNULL(#SalariedResultSetId, -1) = -1 OR calcs.[SalariedGuid] IN (SELECT [SalariedGuid] FROM ret_SalariedResultSetItems WHERE SalariedResultSetID = #SalariedResultSetId)) AND
(calcs.[SalariedGuid] IN (SELECT * FROM #AccessibleSalariedGuids))
When a bug appears I have to fix the problem in both stored procedures, to avoid duplication I wanted Where clauses in a function and call the function in stored procedures,
But I don't know how?
This is how I would approach this:
If you're using Microsoft sql-server, you can make transact-sql code.
Convert your sql procedure into a string and make the Where clause a text variable that you declare elsewhere.
So it's creating a meta- procedure.
For eg.
DECLARE #whereClause LONGTEXT;
DECLARE #SQLString LONGTEXT;
SET #whereClause = 'i=1'
SET #SQLString = 'SELECT * FROM table WHERE' & #whereClause
sp_executesql SQLString

Parameterized stored procedure union all which is conditional with left joins

I want to do, I think, a UNION ALL query so I can return the results from my order table based on the manufacturer id entered in a search field.
Order links to > OrderItem which then can be linked to Product.
I have manually typed up the query, and it works but I'm having trouble making it conditional in my stored procedure.
Here is the query I typed up manually:
SELECT TOP 100 *
FROM [Test].[dbo].[Order] o
LEFT JOIN [Test].[dbo].[OrderItem] oi ON oi.[OrderId] = o.[Id]
LEFT JOIN [Test].[dbo].[Product] p ON p.[Id] = oi.[ProductId]
WHERE p.[ManufacturerId] = 'mid'
Here is my stored procedure:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[OrderLoadAllPaged]
#OrderId INT = 0,
#CustomerId INT = 0,
#ProductId INT = 0,
#WarehouseId INT = 0,
#BillingCountryId INT = 0,
#PaymentMethodSystemName NVARCHAR(MAX) = NULL,
#OrderStatusId INT = 0,
#PaymentStatusId INT = 0,
#ShippingStatusId INT = 0,
#BillingEmail NVARCHAR(MAX) = NULL,
#BillingFirstName NVARCHAR(MAX) = NULL,
#BillingLastName NVARCHAR(MAX) = NULL,
#ManCode NVARCHAR(MAX) = NULL,
#Current BIT = NULL,
#ShippingMethod NVARCHAR(MAX) = NULL,
#CreatedFromUtc DATETIME = NULL,
#CreatedToUtc DATETIME = NULL,
#PageIndex INT = 0,
#PageSize INT = 2147483644,
#TotalRecords INT = NULL OUTPUT
AS
BEGIN
DECLARE #sql NVARCHAR(MAX)
SET NOCOUNT ON;
CREATE TABLE #TempTotal (RowNum INT IDENTITY(1,1), id INT);
CREATE INDEX #IK_temp ON #TempTotal (RowNum);
INSERT INTO #TempTotal ([id])
SELECT o.[Id]
FROM [Test].[dbo].[Order] o WITH (NOLOCK)
LEFT JOIN [Test].[dbo].[Address] a ON a.Id = o.BillingAddressId
AND (COALESCE(#BillingEmail, '') <> ''
OR COALESCE(#BillingFirstName, '') <> ''
OR COALESCE(#BillingLastName, '') <> '')
/* LEFT JOIN [Test].[dbo].[OrderItem] oi ON oi.OrderId = o.Id
AND (COALESCE(#ManCode,'') <> '')
LEFT join [Test].[dbo].[Product] p ON p.Id = oi.ProductId
AND (COALESCE(#ManCode, '') <> '')*/
WHERE (#BillingEmail IS NULL OR a.[Email] = #BillingEmail)
AND (#BillingFirstName IS NULL OR a.[FirstName] = #BillingFirstName)
AND (#BillingLastName IS NULL OR a.[LastName] = #BillingLastName)
-- AND (#ManCode IS NULL OR p.[ManufacturerId] = #ManCode)
UNION ALL
(SELECT *
FROM [Test].[dbo].[Product] p
LEFT JOIN [Test].[dbo].[OrderItem] oi ON oi.[OrderId] = o.[Id]
LEFT JOIN [Test].[dbo].[Product] p ON p.[Id] = oi.[ProductId]
WHERE (#ManCode IS NULL OR p.[ManufacturerId] = #ManCode))
AND -- here is error
o.[Deleted] = 0
AND (o.[Id] = #OrderId OR #OrderId = 0)
AND (o.[CustomerId] = #CustomerId OR #CustomerId = 0)
AND (o.[WarehouseId] = #WarehouseId OR #WarehouseId = 0)
AND (#PaymentMethodSystemName IS NULL OR o.[PaymentMethodSystemName] = #PaymentMethodSystemName)
AND (o.[OrderStatusId] = #OrderStatusId OR #OrderStatusId = 0)
AND (o.[PaymentStatusId] = #PaymentStatusId OR #PaymentStatusId = 0)
AND (o.[ShippingStatusId] = #ShippingStatusId OR #ShippingStatusId = 0)
AND ((o.[OrderStatusId] != '40' AND o.[OrderStatusId] != '30' AND ((o.[ShippingStatusId] != '30' OR o.[ShippingStatusId] != '40') AND o.[Printed] = '0' AND (o.[PaymentStatusId] != '30' OR o.[PaymentStatusId] != '35' OR o.[PaymentStatusId] != '40'))) OR #Current = 0)
AND o.[CreatedOnUtc] >= ISNULL(#CreatedFromUtc, '1/1/1900')
AND o.[CreatedOnUtc] < ISNULL(#CreatedToUtc, '1/1/2999')
ORDER BY
o.[CreatedOnUtc] DESC;
--paging
DECLARE #PageLowerBound INT
SET #PageLowerBound = #PageSize * #PageIndex
-- Return the paged records
SELECT
[Id], [OrderGuid], [StoreId], [CustomerId],
[BillingAddressId], [ShippingAddressId],
[OrderStatusId], [ShippingStatusId],
[PaymentStatusId], [PaymentMethodSystemName],
[TaxRates], [OrderTax], [OrderDiscount], [OrderTotal],
[ShippingMethod], [CustomValuesXml], [Deleted],
[CreatedOnUtc], [EditedStatusId],
[WarehouseId], [PrintedOnUtc]
FROM
[Test].[dbo].[Order] ord
WHERE
ord.[Id] IN (SELECT id FROM #TempTotal tt)
ORDER BY
ord.[CreatedOnUtc] DESC
OFFSET #PageLowerBound ROWS FETCH NEXT #PageSize ROWS ONLY;
--total records
SELECT #TotalRecords = COUNT(*) FROM #TempTotal;
DROP TABLE #TempTotal
END
I'm not sure if UNION ALL is what I need but I feel like it is. I also tried the left joins which are commented out but didn't have any luck there.
Also here is a screenshot of the error at the AND statement.
Anyone able to help me here?
USE [Test]
GO
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[OrderLoadAllPaged]
#OrderId int = 0,
#CustomerId int = 0,
#ProductId int = 0,
#WarehouseId int = 0,
#BillingCountryId int = 0,
#PaymentMethodSystemName nvarchar(max) = null,
#OrderStatusId int = 0,
#PaymentStatusId int = 0,
#ShippingStatusId int = 0,
#BillingEmail nvarchar(max) = null,
#BillingFirstName nvarchar(max) = null,
#BillingLastName nvarchar(max) = null,
#ManCode nvarchar(max) = null,
#Current bit = null,
#ShippingMethod nvarchar(max) = null,
#CreatedFromUtc datetime = null,
#CreatedToUtc datetime = null,
#PageIndex int = 0,
#PageSize int = 2147483644,
#TotalRecords int = null OUTPUT
AS
BEGIN
DECLARE
#sql nvarchar(max)
SET NOCOUNT ON;
create table #TempTotal (RowNum int identity(1,1), id int);
create index #IK_temp on #TempTotal (RowNum);
INSERT INTO #TempTotal ([id])
SELECT o.[Id]
FROM [Test].[dbo].[Order] o with (NOLOCK)
LEFT join [Test].[dbo].[Address] a on a.Id = o.BillingAddressId and (
coalesce(#BillingEmail,'') <> ''
or coalesce(#BillingFirstName,'') <> ''
or coalesce(#BillingLastName,'') <> ''
)
/*LEFT join [Test].[dbo].[OrderItem] oi on oi.OrderId = o.Id and (
coalesce(#ManCode,'') <> ''
)
LEFT join [Test].[dbo].[Product] p on p.Id = oi.ProductId and (
coalesce(#ManCode,'') <> ''
)*/
WHERE (#BillingEmail IS null OR a.[Email] = #BillingEmail)
AND (#BillingFirstName IS null OR a.[FirstName] = #BillingFirstName)
AND (#BillingLastName IS null OR a.[LastName] = #BillingLastName)
--AND (#ManCode IS null OR p.[ManufacturerId] = #ManCode)
UNION ALL
select oi.[Id] from [Test].[dbo].[Product] p
LEFT JOIN [Test].[dbo].[OrderItem] oi ON oi.[OrderId] = o.[Id]
LEFT JOIN [Test].[dbo].[Product] p ON p.[Id] = oi.[ProductId]
WHERE (#ManCode IS null OR p.[ManufacturerId] = #ManCode)
AND -- here is error
o.[Deleted] = 0
AND (o.[Id] = #OrderId OR #OrderId = 0)
AND (o.[CustomerId] = #CustomerId OR #CustomerId = 0)
AND (o.[WarehouseId] = #WarehouseId OR #WarehouseId = 0)
AND (#PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = #PaymentMethodSystemName)
AND (o.[OrderStatusId] = #OrderStatusId OR #OrderStatusId = 0)
AND (o.[PaymentStatusId] = #PaymentStatusId OR #PaymentStatusId = 0)
AND (o.[ShippingStatusId] = #ShippingStatusId OR #ShippingStatusId = 0)
AND ((o.[OrderStatusId] != '40' AND o.[OrderStatusId] != '30' AND ((o.[ShippingStatusId] != '30' OR o.[ShippingStatusId] != '40') AND o.[Printed] = '0' AND (o.[PaymentStatusId] != '30' OR o.[PaymentStatusId] != '35' OR o.[PaymentStatusId] != '40'))) OR #Current = 0)
AND o.[CreatedOnUtc] >= ISNULL(#CreatedFromUtc, '1/1/1900')
AND o.[CreatedOnUtc] < ISNULL(#CreatedToUtc, '1/1/2999')
ORDER BY o.[CreatedOnUtc] DESC;
--paging
DECLARE #PageLowerBound int
SET #PageLowerBound = #PageSize * #PageIndex
-- Return the paged records
select [Id]
,[OrderGuid]
,[StoreId]
,[CustomerId]
,[BillingAddressId]
,[ShippingAddressId]
,[OrderStatusId]
,[ShippingStatusId]
,[PaymentStatusId]
,[PaymentMethodSystemName]
,[TaxRates]
,[OrderTax]
,[OrderDiscount]
,[OrderTotal]
,[ShippingMethod]
,[CustomValuesXml]
,[Deleted]
,[CreatedOnUtc]
,[EditedStatusId]
,[WarehouseId]
,[PrintedOnUtc]
from [Test].[dbo].[Order] ord
where ord.[Id] in (
select id
from #TempTotal tt
)
ORDER BY ord.[CreatedOnUtc] DESC
OFFSET #PageLowerBound ROWS FETCH NEXT #PageSize ROWS ONLY;
--total records
select #TotalRecords = count(*) from #TempTotal;
DROP TABLE #TempTotal
END
ALTER PROCEDURE [dbo].[OrderLoadAllPaged]
#OrderId int = 0,
#CustomerId int = 0,
#ProductId int = 0,
#WarehouseId int = 0,
#BillingCountryId int = 0,
#PaymentMethodSystemName nvarchar(max) = null,
#OrderStatusId int = 0,
#PaymentStatusId int = 0,
#ShippingStatusId int = 0,
#BillingEmail nvarchar(max) = null,
#BillingFirstName nvarchar(max) = null,
#BillingLastName nvarchar(max) = null,
#ManCode nvarchar(max) = null,
#Current bit = null,
#ShippingMethod nvarchar(max) = null,
#CreatedFromUtc datetime = null,
#CreatedToUtc datetime = null,
#PageIndex int = 0,
#PageSize int = 2147483644,
#TotalRecords int = null OUTPUT
AS
BEGIN
DECLARE
#sql nvarchar(max)
SET NOCOUNT ON;
create table #TempTotal (RowNum int identity(1,1), id int);
create index #IK_temp on #TempTotal (RowNum);
INSERT INTO #TempTotal ([id])
SELECT o.[Id]
FROM [Test].[dbo].[Order] o with (NOLOCK)
LEFT join [Test].[dbo].[Address] a on a.Id = o.BillingAddressId and (
coalesce(#BillingEmail,'') <> ''
or coalesce(#BillingFirstName,'') <> ''
or coalesce(#BillingLastName,'') <> ''
)
/*LEFT join [Test].[dbo].[OrderItem] oi on oi.OrderId = o.Id and (
coalesce(#ManCode,'') <> ''
)
LEFT join [Test].[dbo].[Product] p on p.Id = oi.ProductId and (
coalesce(#ManCode,'') <> ''
)*/
WHERE (#BillingEmail IS null OR a.[Email] = #BillingEmail)
AND (#BillingFirstName IS null OR a.[FirstName] = #BillingFirstName)
AND (#BillingLastName IS null OR a.[LastName] = #BillingLastName)
--AND (#ManCode IS null OR p.[ManufacturerId] = #ManCode)
UNION ALL
SELECT * FROM
(
select * from [Test].[dbo].[Product] p
LEFT JOIN [Test].[dbo].[OrderItem] oi ON oi.[OrderId] = o.[Id]
LEFT JOIN [Test].[dbo].[Product] p ON p.[Id] = oi.[ProductId]
WHERE (#ManCode IS null OR p.[ManufacturerId] = #ManCode)
)O
WHERE -- here is error (Here Procdure Can't Findout the object O) ---So, take 'O' Object Outside........
o.[Deleted] = 0
AND (o.[Id] = #OrderId OR #OrderId = 0)
AND (o.[CustomerId] = #CustomerId OR #CustomerId = 0)
AND (o.[WarehouseId] = #WarehouseId OR #WarehouseId = 0)
AND (#PaymentMethodSystemName IS null OR o.[PaymentMethodSystemName] = #PaymentMethodSystemName)
AND (o.[OrderStatusId] = #OrderStatusId OR #OrderStatusId = 0)
AND (o.[PaymentStatusId] = #PaymentStatusId OR #PaymentStatusId = 0)
AND (o.[ShippingStatusId] = #ShippingStatusId OR #ShippingStatusId = 0)
AND ((o.[OrderStatusId] != '40' AND o.[OrderStatusId] != '30' AND ((o.[ShippingStatusId] != '30' OR o.[ShippingStatusId] != '40') AND o.[Printed] = '0' AND (o.[PaymentStatusId] != '30' OR o.[PaymentStatusId] != '35' OR o.[PaymentStatusId] != '40'))) OR #Current = 0)
AND o.[CreatedOnUtc] >= ISNULL(#CreatedFromUtc, '1/1/1900')
AND o.[CreatedOnUtc] < ISNULL(#CreatedToUtc, '1/1/2999')
ORDER BY o.[CreatedOnUtc] DESC;
--paging
DECLARE #PageLowerBound int
SET #PageLowerBound = #PageSize * #PageIndex
-- Return the paged records
select [Id]
,[OrderGuid]
,[StoreId]
,[CustomerId]
,[BillingAddressId]
,[ShippingAddressId]
,[OrderStatusId]
,[ShippingStatusId]
,[PaymentStatusId]
,[PaymentMethodSystemName]
,[TaxRates]
,[OrderTax]
,[OrderDiscount]
,[OrderTotal]
,[ShippingMethod]
,[CustomValuesXml]
,[Deleted]
,[CreatedOnUtc]
,[EditedStatusId]
,[WarehouseId]
,[PrintedOnUtc]
from [Test].[dbo].[Order] ord
where ord.[Id] in (
select id
from #TempTotal tt
)
ORDER BY ord.[CreatedOnUtc] DESC
OFFSET #PageLowerBound ROWS FETCH NEXT #PageSize ROWS ONLY;
--total records
select #TotalRecords = count(*) from #TempTotal;
DROP TABLE #TempTotal
END
Note:- (Here Procdure Can't Findout the object O) ---So, take 'O' Object Outside........If can't find out object (alias) ...so it will not work in where condition......
Ok so I figured this out, I needed to use a select statement with a left join which is dependent on the #ManCode parameter not being null.
Paging still works fine too, without having to add extra temp tables :)
Here is how I did it:
AND (#ManCode IS null OR EXISTS (
SELECT [OrderId], [ManufacturerId] FROM [Test].[dbo].[OrderItem] oi with (NOLOCK)
LEFT join [Test].[dbo].[Product] p on p.ManufacturerId = oi.ManufacturerId
WHERE oi.OrderId = o.Id AND p.[ManufacturerId] = '' + #ManCode + ''))
So now my full updated stored procedure looks like so:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
ALTER PROCEDURE [dbo].[OrderLoadAllPaged]
#OrderId INT = 0,
#CustomerId INT = 0,
#ProductId INT = 0,
#WarehouseId INT = 0,
#BillingCountryId INT = 0,
#PaymentMethodSystemName NVARCHAR(MAX) = NULL,
#OrderStatusId INT = 0,
#PaymentStatusId INT = 0,
#ShippingStatusId INT = 0,
#BillingEmail NVARCHAR(MAX) = NULL,
#BillingFirstName NVARCHAR(MAX) = NULL,
#BillingLastName NVARCHAR(MAX) = NULL,
#ManCode NVARCHAR(MAX) = NULL,
#Current BIT = NULL,
#ShippingMethod NVARCHAR(MAX) = NULL,
#CreatedFromUtc DATETIME = NULL,
#CreatedToUtc DATETIME = NULL,
#PageIndex INT = 0,
#PageSize INT = 2147483644,
#TotalRecords INT = NULL OUTPUT
AS
BEGIN
DECLARE #sql NVARCHAR(MAX)
SET NOCOUNT ON;
CREATE TABLE #TempTotal (RowNum INT IDENTITY(1,1), id INT);
CREATE INDEX #IK_temp ON #TempTotal (RowNum);
INSERT INTO #TempTotal ([id])
SELECT o.[Id]
FROM [Test].[dbo].[Order] o WITH (NOLOCK)
LEFT JOIN [Test].[dbo].[Address] a ON a.Id = o.BillingAddressId
AND (COALESCE(#BillingEmail, '') <> ''
OR COALESCE(#BillingFirstName, '') <> ''
OR COALESCE(#BillingLastName, '') <> '')
WHERE (#BillingEmail IS NULL OR a.[Email] = #BillingEmail)
AND (#BillingFirstName IS NULL OR a.[FirstName] = #BillingFirstName)
AND (#BillingLastName IS NULL OR a.[LastName] = #BillingLastName)
AND (#ManCode IS null OR EXISTS (
SELECT [OrderId], [ManufacturerId] FROM [Test].[dbo].[OrderItem] oi with (NOLOCK)
LEFT join [Test].[dbo].[Product] p on p.ManufacturerId = oi.ManufacturerId
WHERE oi.OrderId = o.Id AND p.[ManufacturerId] = '' + #ManCode + ''))
AND
o.[Deleted] = 0
AND (o.[Id] = #OrderId OR #OrderId = 0)
AND (o.[CustomerId] = #CustomerId OR #CustomerId = 0)
AND (o.[WarehouseId] = #WarehouseId OR #WarehouseId = 0)
AND (#PaymentMethodSystemName IS NULL OR o.[PaymentMethodSystemName] = #PaymentMethodSystemName)
AND (o.[OrderStatusId] = #OrderStatusId OR #OrderStatusId = 0)
AND (o.[PaymentStatusId] = #PaymentStatusId OR #PaymentStatusId = 0)
AND (o.[ShippingStatusId] = #ShippingStatusId OR #ShippingStatusId = 0)
AND ((o.[OrderStatusId] != '40' AND o.[OrderStatusId] != '30' AND ((o.[ShippingStatusId] != '30' OR o.[ShippingStatusId] != '40') AND o.[Printed] = '0' AND (o.[PaymentStatusId] != '30' OR o.[PaymentStatusId] != '35' OR o.[PaymentStatusId] != '40'))) OR #Current = 0)
AND o.[CreatedOnUtc] >= ISNULL(#CreatedFromUtc, '1/1/1900')
AND o.[CreatedOnUtc] < ISNULL(#CreatedToUtc, '1/1/2999')
ORDER BY
o.[CreatedOnUtc] DESC;
--paging
DECLARE #PageLowerBound INT
SET #PageLowerBound = #PageSize * #PageIndex
-- Return the paged records
SELECT
[Id], [OrderGuid], [StoreId], [CustomerId],
[BillingAddressId], [ShippingAddressId],
[OrderStatusId], [ShippingStatusId],
[PaymentStatusId], [PaymentMethodSystemName],
[TaxRates], [OrderTax], [OrderDiscount], [OrderTotal],
[ShippingMethod], [CustomValuesXml], [Deleted],
[CreatedOnUtc], [EditedStatusId],
[WarehouseId], [PrintedOnUtc]
FROM
[Test].[dbo].[Order] ord
WHERE
ord.[Id] IN (SELECT id FROM #TempTotal tt)
ORDER BY
ord.[CreatedOnUtc] DESC
OFFSET #PageLowerBound ROWS FETCH NEXT #PageSize ROWS ONLY;
--total records
SELECT #TotalRecords = COUNT(*) FROM #TempTotal;
DROP TABLE #TempTotal
END

How to get parent Id from a run time generated row_number() as unique id in SQL

I have removed while loop used before but furnishing exact results. Now everything works fine except parentkey.
How to get "parentkey" in the stored procedure perfectly??
The procedure furnishes wrong results if more than 1 same parent is addded in same/different level of bom. The results shows one parent for all childs. It should show both parents separately with childs. The following part does not furnish exact result in case explained above.
(SELECT MAX(e.idcolumn) FROM #tExplode E WHERE e.fcomponent = b.fparent AND e.fcomprev = b.fparentrev AND e.cfacilityid = b.pfacilityid AND e.idcolumn > 0 ) As parentkey
IF EXISTS (SELECT name FROM sysobjects WHERE name = 'M2M_Std_BOM_Explosion' AND type = 'P')
DROP PROCEDURE M2M_Std_BOM_Explosion
GO
CREATE Procedure [dbo].[M2M_Std_BOM_Explosion]
#pcPartNo CHAR(25),
#pcPartRev CHAR(3),
#pcFac CHAR(20),
#plIndent Bit
As
Begin
set nocount on
if object_id('tempdb..#tExplode') is not null drop table #tExplode
declare #sql as varchar(max) = ''
create table #tExplode
(
ID int not null,
lvl int not null,
CompPath varchar(8000),
ItmPath varchar(8000),
display varchar(100),
fcomponent varchar(25),
cfacilityid varchar(20),
fcomprev varchar(3),
fparent varchar(25),
fparentrev varchar(3),
pfacilityid varchar(20),
fitem varchar(6),
fqty numeric(15,5),
fsumqty numeric(15,5),
fst_ef_dt datetime,
fend_ef_dt datetime,
bomid int,
fnoperno int,
fltooling bit,
fbommemo varchar(8000),
fprodcl varchar(20),
flfssvc bit,
idcolumn Integer,
timestamp_column timestamp,
flextend bit,
fcompudrev varchar(3),
fcparudrev varchar(3),
forder int
)
Insert into #tExplode( ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,bomid,fnoperno,fltooling,fbommemo,flfssvc,flextend,
fcompudrev,fcparudrev,forder,idcolumn)
SELECT 1,
0,
Cast(Rtrim(ltrim(#pcFac))+rtrim(ltrim(#pcPartNo))+rtrim(ltrim(#pcPartRev)) as varchar(8000)),
Cast(rtrim(ltrim(#pcFac))+rtrim(ltrim(#pcPartNo))+rtrim(ltrim(#pcPartRev)) as Varchar(8000)),
cast(1 AS varchar(100)),
#pcPartNo,
#pcFac,
#pcPartRev,
'',
'',
'',
'',
1,
1,
{d '1900-01-01'},
{d '1900-01-01'},
0,
'',
0,
'',
0,
0,
'',
'',
0,
0
FROM (SELECT #pcFac fac,
#pcPartNo fpartno,
#pcPartRev frev) x
LEFT JOIN inrtgc i On i.fac=x.fac And i.fpartno=x.fpartno And i.fcpartrev=x.frev
; WITH t AS (
select ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,
bomid,
fnoperno,
fltooling,
fbommemo,
flfssvc,
flextend,
fcompudrev,
fcparudrev,
forder
from #tExplode
UNION ALL
SELECT b.identity_column,
t.lvl+1,
rtrim(ltrim(t.CompPath)) + '!' + rtrim(ltrim(b.pfacilityid)) + rtrim(ltrim(b.fcomponent)) + Replicate(' ',25-Len(rtrim(ltrim(b.fcomponent))))+ rtrim(ltrim(b.fcomprev + '!')),
rtrim(ltrim(t.ItmPath)) + '!' + rtrim(ltrim(b.fitem)),
Cast(replicate(' ',2*t.lvl) + b.fcomponent as Varchar(100)),
Cast(b.fcomponent as Varchar(25)),
Cast(b.cfacilityid as Varchar(20)),
Cast(b.fcomprev as Varchar(3)),
Cast(b.fparent as Varchar(25)),
Cast(b.fparentrev as Varchar(3)),
Cast(b.pfacilityid as Varchar(20)),
Cast(b.fitem as varchar(6)),
b.fqty,
Cast(CASE
WHEN b.flextend = 1 THEN b.fqty * ISNULL(t.fsumqty, cast(1 AS numeric(15,5)))
ELSE b.fqty
END as Numeric(15,5)),
b.fst_ef_dt,
b.fend_ef_dt,
b.identity_column,
ISNULL(b.fnoperno,cast(0 AS int)),
b.fltooling,
Cast(b.fbommemo as Varchar(8000)),
b.flfssvc,
b.flextend,
Cast(b.fcompudrev as Varchar(3)),
Cast(b.fcparudrev as Varchar(3)),
0
FROM inboms b
inner join t ON b.pFacilityID = t.cFacilityID
AND b.fparent = t.fcomponent
AND b.fparentrev = t.fcomprev
)
insert into #tExplode
(ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,
bomid,
fnoperno,
fltooling,fbommemo,flfssvc,
flextend,
fcompudrev,fcparudrev,forder,idcolumn)
select ID,lvl,CompPath,ItmPath,display,fcomponent,cfacilityid,fcomprev,
fparent,fparentrev,pfacilityid,fitem,fqty,fsumqty,fst_ef_dt,
fend_ef_dt,
bomid,
fnoperno,
fltooling,fbommemo,
flfssvc,
flextend,
fcompudrev,fcparudrev,forder,row_number() over (order by lvl,comppath,cfacilityid,fcomponent,fcomprev,forder) from t
Set #sql = 'select b.idcolumn,b.lvl,
b.comppath,
b.itmpath,
b.display,
CASE WHEN m.fluseudrev = 1 THEN b.fcompudrev ELSE b.fcomprev END as disprev,
b.fitem,
fsource,
b.fqty,
CASE when b.flextend = 1 then b.fsumqty ELSE ((b.fqty * ISNULL(b.fsumqty, cast(1 AS numeric(15,5))))/Isnull(i.fSpq,1)) END as fsumqty,
fmeasure,
b.fnoperno,
CASE WHEN inbomm.fpartno IS NULL THEN SPACE(1) ELSE ''*'' END as isparent, --Working
b.fst_ef_dt,
b.fend_ef_dt,
b.bomid,
b.fcomponent,
b.cfacilityid,
b.fcomprev,
m.fdescript as fdesc,
b.fparent,
b.fparentrev,
b.pfacilityid,
ISNULL(m.identity_column, CAST(0 As Int)) as partid,
fidims,
Case When m.fcstscode=''O'' Then ''Obsolete''
Else
CASE WHEN NOT ((b.fst_ef_dt IS NULL) OR (b.fst_ef_dt={d ''1900-01-01''})) AND
DATEDIFF(day,b.fst_ef_dt, GetDate()) < 0
THEN ''Future''
WHEN NOT ((b.fend_ef_dt IS NULL) OR (b.fend_ef_dt={d ''1900-01-01''})) AND
DATEDIFF(day,b.fEnd_ef_dt, GETDATE()) > 0
THEN ''Expired''
ELSE ''Current''
END
End as effectivity,
b.fltooling,
b.fbommemo,
m.fprodcl,
fllotreqd,
b.flfssvc,
b.timestamp_column,
(SELECT MAX(e.idcolumn) FROM #tExplode E WHERE e.fcomponent = b.fparent AND e.fcomprev = b.fparentrev AND e.cfacilityid = b.pfacilityid AND e.idcolumn > 0 ) As parentkey,
b.flextend,
m.fluseudrev,
b.fcompudrev,
b.fcparudrev,
b.forder
from #tExplode b LEFT OUTER JOIN inmastx m ON
b.cFacilityID = m.fac AND
b.fcomponent = m.fpartno AND
b.fcomprev = m.frev
LEFT OUTER JOIN inbomm ON
b.pfacilityid = inbomm.facilityid AND
b.fComponent = InBomm.fPartno AND
b.fCompRev = InBomm.fcPartRev
LEFT OUTER JOIN inrtgc i ON
b.pfacilityid = i.fac AND
b.fComponent = i.fPartno AND
b.fCompRev = i.fcPartRev
where ' + case when #plIndent= 1 then 'b.lvl >= 1' else 'b.lvl = 1' end + '
order by ' + case when #plIndent= 1 then 'b.comppath,b.cfacilityid,b.fcomponent,b.fcomprev,b.forder' else 'b.comppath,b.forder' end + ''
Exec(#sql)
drop table #tExplode
end
--How to get "parentkey" in the stored procedure perfectly??
--The procedure furnishes wrong results if more than 1 same parent is addded in --same/different level of bom. The results shows one parent for all childs.

SQL Server : query simplification - many joins and a giant WHERE section

I am trying to run a stored procedure, but it keeps timing out from using too much ram. The server its being run on only has 1.5GB of ram to work with. Here is the original query:
CREATE PROCEDURE [dbo].[rpt_Registrations_Std]
#Action nvarchar(50) = '', -- Action is field name for now
#DATE_OPRT_FROM datetime = null,
#DATE_OPRT_TO datetime = null,
#DATE_EFFECTIVE_FROM datetime = null,
#DATE_EFFECTIVE_TO datetime = null,
#DATE_MODIFIED_FROM datetime = null,
#DATE_MODIFIED_TO datetime = null,
#ASSET_NO nvarchar(4000) = '',
#ASSET_NO_FROM nvarchar(20) = '',
#ASSET_NO_TO nvarchar(20) = '',
#HOLDER_CD nvarchar(4000) = '',
#HOLDER_CD_FROM nvarchar(10) = '',
#HOLDER_CD_TO nvarchar(10) = '',
#SITE_CD nvarchar(4000) = '',
#SITE_CD_FROM nvarchar(10) = '',
#SITE_CD_TO nvarchar(10) = '',
#ASSETCODE nvarchar(4000) = '',
#ASSETCODE_FROM nvarchar(10) = null,
#ASSETCODE_TO nvarchar(10) = null,
#FUND_CD nvarchar(4000) = '',
#FUND_CD_FROM nvarchar(10) = '',
#FUND_CD_TO nvarchar(10) = '',
#PO_NO nvarchar(4000) = '',
#PO_NO_FROM nvarchar(15) = '',
#PO_NO_TO nvarchar(15) = '',
#STATUS nvarchar(4000) = '',
#STATUS_FROM int = null,
#STATUS_TO int = null,
#UNITPRICE_FROM money = null,
#UNITPRICE_TO money = null,
#CAPITALIZED bit = Null
AS
BEGIN
select cast(data as nvarchar) ASSET_NO INTO #asset_nos from dbo.split(#ASSET_NO,',')
where data is not null
select cast(data as nvarchar) HOLDER_CD INTO #holders from dbo.split(#HOLDER_CD,',')
where data is not null
select cast(data as nvarchar) SITE_CD INTO #site from dbo.split(#SITE_CD,',')
where data is not null
select cast(data as nvarchar) ASSETCODE INTO #assetcode from dbo.split(#ASSETCODE,',')
where data is not null
select cast(data as nvarchar) FUND_CD INTO #fundcode from dbo.split(#FUND_CD,',')
where data is not null
select cast(data as nvarchar) PO_NO INTO #pono from dbo.split(#PO_NO,',')
where data is not null
select cast(data as int) [STATUS] INTO #status from dbo.split(#STATUS,',')
where data is not null
DECLARE #FIELD nvarchar(20)
SET #FIELD = #Action
--- FIELD Def for report From here
SELECT
a.ASSET_NO
,a.DATE_RECEIVED as DATE_OPRT
,a.DATE_EFFECTIVE_REGISTERED as DATE_EFFECTIVE
,a.DATE_REGISTERED as DATE_MODIFIED
,a.USER_ID_REGIST as USER_ID_MODIFY
,a.DESC_1
,a.DESC_2
,a.DESC_AX
,a.DESC_1
+ CASE WHEN IsNull(a.DESC_2, '') = '' THEN '' ELSE ' ' + a.DESC_2 END
+ CASE WHEN IsNull(a.DESC_AX, '') = '' THEN '' ELSE ' ' + a.DESC_AX END
as ASSET_DESC
,a.MANUFACTURER
,a.MODEL
,a.SERIAL_NO
,a.WEIGHT
,a.ASSETCODE
,a.SITE_CD
,a.ROOM_CD
,a.BUILDING_CD
,a.HOLDER_CD
,a.HOLDER_DESC
,a.STATUS
,Left(a.STATUS_DESC, 10) as STATUS_DESC
,ac.CODE_DESCRIPTION
,a.RM_DESC_1 AS ROOM_DESC
,a.SITE_NAME_1 AS SITE_NAME
,a.BUILDING_NAME
,a.DATE_RECEIVED
,fin.DATE_INSERVICE
,fin.ORIG_COST
,fin.QTY
,fin.PM_FUND_CD as FUND_CD
,fin.CAPITALIZED
,fnd.FUND_DESC
,a.PM_PO_NO as PO_NO
-- Initial values
,u.ORIG_COST AS INIT_COST
,ui.ASSETCODE AS INIT_ASSETCODE
,uR.SITE_CD AS INIT_SITE_CD
,u.ROOM_CD AS INIT_ROOM_CD
,uR.BUILDING_CD AS INIT_BUILDING_CD
,uR.RM_DESC_1 AS INIT_ROOM_DESC
,uR.BUILDING_NAME AS INIT_BUILDING_NAME
,uR.SITE_NAME_1 AS INIT_SITE_NAME
,u.HOLDER_CD AS INIT_HOLDER_CD
,uH.ORG_DESC AS INIT_HOLDER_DESC
,uac.CODE_DESCRIPTION AS INIT_CODE_DESCRIPTION
FROM vAsset as a
LEFT JOIN vAsset_Rgst_Info as u ON a.ASSET_ID = u.ASSET_ID
LEFT JOIN tAssetCode as ac ON a.ASSETCODE = ac.ASSETCODE
LEFT JOIN tAssetFin as fin ON a.ASSET_NO = fin.ASSET_NO
LEFT JOIN tFunding as fnd ON fin.PM_FUND_CD = fnd.FUND_CD
LEFT JOIN tItemCatalog as ui ON u.ITEM_CD = ui.ITEM_CD
LEFT jOIN tAssetCode as uac ON ui.ASSETCODE = uac.ASSETCODE
LEFT JOIN vRoom as uR ON u.ROOM_CD = uR.ROOM_CD
LEFT JOIN tOrganization as uH ON u.HOLDER_CD = uH.ORG_CD
WHERE
( #DATE_OPRT_FROM is null OR a.DATE_RECEIVED >= #DATE_OPRT_FROM )
AND ( #DATE_OPRT_TO is null OR a.DATE_RECEIVED <= #DATE_OPRT_TO )
AND ( #DATE_EFFECTIVE_FROM is null OR a.DATE_EFFECTIVE_REGISTERED >= #DATE_EFFECTIVE_FROM )
AND ( #DATE_EFFECTIVE_TO is null OR a.DATE_EFFECTIVE_REGISTERED <= #DATE_EFFECTIVE_TO )
AND ( #DATE_MODIFIED_FROM is null OR a.DATE_REGISTERED >= #DATE_MODIFIED_FROM )
AND ( #DATE_MODIFIED_TO is null OR a.DATE_REGISTERED <= #DATE_MODIFIED_TO )
AND ( #ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))
AND ( #ASSET_NO_FROM = '' OR u.ASSET_NO >= #ASSET_NO_FROM )
AND ( #ASSET_NO_TO = '' OR u.ASSET_NO <= #ASSET_NO_TO )
AND ( #HOLDER_CD = '' OR a.HOLDER_CD in ( SELECT HOLDER_CD from #holders ))
AND ( #HOLDER_CD_FROM = '' OR a.HOLDER_CD >= #HOLDER_CD_FROM )
AND ( #HOLDER_CD_TO = '' OR a.HOLDER_CD <= #HOLDER_CD_TO )
AND ( #SITE_CD = '' OR a.SITE_CD in ( SELECT SITE_CD from #site ))
AND ( #SITE_CD_FROM = '' OR a.SITE_CD >= #SITE_CD_FROM )
AND ( #SITE_CD_TO = '' OR a.SITE_CD <= #SITE_CD_TO )
AND ( #ASSETCODE = '' OR a.ASSETCODE in ( SELECT ASSETCODE from #assetcode ))
AND ( #ASSETCODE_FROM is null OR a.ASSETCODE >= #ASSETCODE_FROM )
AND ( #ASSETCODE_TO is null OR a.ASSETCODE <= #ASSETCODE_TO )
AND ( #FUND_CD = '' OR PM_FUND_CD in ( SELECT FUND_CD from #fundcode ))
AND ( #FUND_CD_FROM = '' OR fin.PM_FUND_CD >= #FUND_CD_FROM )
AND ( #FUND_CD_TO = '' OR fin.PM_FUND_CD <= #FUND_CD_TO )
AND ( #PO_NO = '' OR a.PM_PO_NO in ( SELECT PO_NO from #pono ))
AND ( #PO_NO_FROM = '' OR a.PM_PO_NO >= #PO_NO_FROM )
AND ( #PO_NO_TO = '' OR a.PM_PO_NO <= #PO_NO_TO )
AND ( #STATUS = '' OR a.STATUS in ( SELECT [STATUS] from #status ))
AND ( #STATUS_FROM is null OR a.STATUS >= #STATUS_FROM )
AND ( #STATUS_TO is null OR a.STATUS <= #STATUS_TO )
AND ( #UNITPRICE_FROM is null OR fin.UNIT_COST >= #UNITPRICE_FROM )
AND ( #UNITPRICE_TO is null OR fin.UNIT_COST <= #UNITPRICE_TO )
AND ( #CAPITALIZED is null OR fin.CAPITALIZED = #CAPITALIZED )
END -- proc
I added some subquerying to speed it up, but it still times out:
ALTER PROCEDURE [dbo].[rpt_Registrations_Std]
#Action nvarchar(50) = '', -- Action is field name for now
#DATE_OPRT_FROM datetime = null,
#DATE_OPRT_TO datetime = null,
#DATE_EFFECTIVE_FROM datetime = null,
#DATE_EFFECTIVE_TO datetime = null,
#DATE_MODIFIED_FROM datetime = null,
#DATE_MODIFIED_TO datetime = null,
#ASSET_NO nvarchar(4000) = '',
#ASSET_NO_FROM nvarchar(20) = '',
#ASSET_NO_TO nvarchar(20) = '',
#HOLDER_CD nvarchar(4000) = '',
#HOLDER_CD_FROM nvarchar(10) = '',
#HOLDER_CD_TO nvarchar(10) = '',
#SITE_CD nvarchar(4000) = '',
#SITE_CD_FROM nvarchar(10) = '',
#SITE_CD_TO nvarchar(10) = '',
#ASSETCODE nvarchar(4000) = '',
#ASSETCODE_FROM nvarchar(10) = null,
#ASSETCODE_TO nvarchar(10) = null,
#FUND_CD nvarchar(4000) = '',
#FUND_CD_FROM nvarchar(10) = '',
#FUND_CD_TO nvarchar(10) = '',
#PO_NO nvarchar(4000) = '',
#PO_NO_FROM nvarchar(15) = '',
#PO_NO_TO nvarchar(15) = '',
#STATUS nvarchar(4000) = '',
#STATUS_FROM int = null,
#STATUS_TO int = null,
#UNITPRICE_FROM money = null,
#UNITPRICE_TO money = null,
#CAPITALIZED bit = Null
AS
BEGIN
select cast(data as nvarchar) ASSET_NO INTO #asset_nos from dbo.split(#ASSET_NO,',')
where data is not null
select cast(data as nvarchar) HOLDER_CD INTO #holders from dbo.split(#HOLDER_CD,',')
where data is not null
select cast(data as nvarchar) SITE_CD INTO #site from dbo.split(#SITE_CD,',')
where data is not null
select cast(data as nvarchar) ASSETCODE INTO #assetcode from dbo.split(#ASSETCODE,',')
where data is not null
select cast(data as nvarchar) FUND_CD INTO #fundcode from dbo.split(#FUND_CD,',')
where data is not null
select cast(data as nvarchar) PO_NO INTO #pono from dbo.split(#PO_NO,',')
where data is not null
select cast(data as int) [STATUS] INTO #status from dbo.split(#STATUS,',')
where data is not null
DECLARE #FIELD nvarchar(20)
SET #FIELD = #Action
--- FIELD Def for report From here
SELECT
a.ASSET_NO
,a.DATE_RECEIVED as DATE_OPRT
,a.DATE_EFFECTIVE_REGISTERED as DATE_EFFECTIVE
,a.DATE_REGISTERED as DATE_MODIFIED
,a.USER_ID_REGIST as USER_ID_MODIFY
,a.DESC_1
,a.DESC_2
,a.DESC_AX
,a.DESC_1
+ CASE WHEN IsNull(a.DESC_2, '') = '' THEN '' ELSE ' ' + a.DESC_2 END
+ CASE WHEN IsNull(a.DESC_AX, '') = '' THEN '' ELSE ' ' + a.DESC_AX END
as ASSET_DESC
,a.MANUFACTURER
,a.MODEL
,a.SERIAL_NO
,a.WEIGHT
,a.ASSETCODE
,a.SITE_CD
,a.ROOM_CD
,a.BUILDING_CD
,a.HOLDER_CD
,a.HOLDER_DESC
,a.STATUS
,Left(a.STATUS_DESC, 10) as STATUS_DESC
,ac.CODE_DESCRIPTION
,a.RM_DESC_1 AS ROOM_DESC
,a.SITE_NAME_1 AS SITE_NAME
,a.BUILDING_NAME
,a.DATE_RECEIVED
,fin.DATE_INSERVICE
,fin.ORIG_COST
,fin.QTY
,fin.PM_FUND_CD as FUND_CD
,fin.CAPITALIZED
,fnd.FUND_DESC
,a.PM_PO_NO as PO_NO
-- Initial values
,u.ORIG_COST AS INIT_COST
,ui.ASSETCODE AS INIT_ASSETCODE
,uR.SITE_CD AS INIT_SITE_CD
,u.ROOM_CD AS INIT_ROOM_CD
,uR.BUILDING_CD AS INIT_BUILDING_CD
,uR.RM_DESC_1 AS INIT_ROOM_DESC
,uR.BUILDING_NAME AS INIT_BUILDING_NAME
,uR.SITE_NAME_1 AS INIT_SITE_NAME
,u.HOLDER_CD AS INIT_HOLDER_CD
,uH.ORG_DESC AS INIT_HOLDER_DESC
,uac.CODE_DESCRIPTION AS INIT_CODE_DESCRIPTION
FROM (SELECT
a.ASSET_NO
,a.ASSET_ID
,a.DATE_EFFECTIVE_REGISTERED
,a.DATE_REGISTERED
,a.USER_ID_REGIST
,a.DESC_1
,a.DESC_2
,a.DESC_AX
,a.MANUFACTURER
,a.MODEL
,a.SERIAL_NO
,a.WEIGHT
,a.ASSETCODE
,a.SITE_CD
,a.ROOM_CD
,a.BUILDING_CD
,a.HOLDER_CD
,a.HOLDER_DESC
,a.STATUS
,a.STATUS_DESC
,a.RM_DESC_1
,a.SITE_NAME_1
,a.BUILDING_NAME
,a.DATE_RECEIVED
,a.PM_PO_NO
FROM vAsset as a WHERE ASSET_NO IN (
SELECT ASSET_NO FROM vAsset as a
WHERE
( #DATE_OPRT_FROM is null OR a.DATE_RECEIVED >= #DATE_OPRT_FROM )
AND ( #DATE_OPRT_TO is null OR a.DATE_RECEIVED <= #DATE_OPRT_TO )
AND ( #DATE_EFFECTIVE_FROM is null OR a.DATE_EFFECTIVE_REGISTERED >= #DATE_EFFECTIVE_FROM )
AND ( #DATE_EFFECTIVE_TO is null OR a.DATE_EFFECTIVE_REGISTERED <= #DATE_EFFECTIVE_TO )
AND ( #DATE_MODIFIED_FROM is null OR a.DATE_REGISTERED >= #DATE_MODIFIED_FROM )
AND ( #DATE_MODIFIED_TO is null OR a.DATE_REGISTERED <= #DATE_MODIFIED_TO )
AND ( #HOLDER_CD = '' OR a.HOLDER_CD in ( SELECT HOLDER_CD from #holders ))
AND ( #HOLDER_CD_FROM = '' OR a.HOLDER_CD >= #HOLDER_CD_FROM )
AND ( #HOLDER_CD_TO = '' OR a.HOLDER_CD <= #HOLDER_CD_TO )
AND ( #SITE_CD = '' OR a.SITE_CD in ( SELECT SITE_CD from #site ))
AND ( #SITE_CD_FROM = '' OR a.SITE_CD >= #SITE_CD_FROM )
AND ( #SITE_CD_TO = '' OR a.SITE_CD <= #SITE_CD_TO )
AND ( #ASSETCODE = '' OR a.ASSETCODE in ( SELECT ASSETCODE from #assetcode ))
AND ( #ASSETCODE_FROM is null OR a.ASSETCODE >= #ASSETCODE_FROM )
AND ( #ASSETCODE_TO is null OR a.ASSETCODE <= #ASSETCODE_TO )
AND ( #PO_NO = '' OR a.PM_PO_NO in ( SELECT PO_NO from #pono ))
AND ( #PO_NO_FROM = '' OR a.PM_PO_NO >= #PO_NO_FROM )
AND ( #PO_NO_TO = '' OR a.PM_PO_NO <= #PO_NO_TO )
AND ( #STATUS = '' OR a.STATUS in ( SELECT [STATUS] from #status ))
AND ( #STATUS_FROM is null OR a.STATUS >= #STATUS_FROM )
AND ( #STATUS_TO is null OR a.STATUS <= #STATUS_TO )
)) as a
LEFT JOIN vAsset_Rgst_Info as u ON a.ASSET_ID = u.ASSET_ID
LEFT JOIN tAssetCode as ac ON a.ASSETCODE = ac.ASSETCODE
LEFT JOIN tAssetFin as fin ON a.ASSET_NO = fin.ASSET_NO
LEFT JOIN tFunding as fnd ON fin.PM_FUND_CD = fnd.FUND_CD
LEFT JOIN tItemCatalog as ui ON u.ITEM_CD = ui.ITEM_CD
LEFT jOIN tAssetCode as uac ON ui.ASSETCODE = uac.ASSETCODE
LEFT JOIN vRoom as uR ON u.ROOM_CD = uR.ROOM_CD
LEFT JOIN tOrganization as uH ON u.HOLDER_CD = uH.ORG_CD
WHERE
( #ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))
AND ( #ASSET_NO_FROM = '' OR u.ASSET_NO >= #ASSET_NO_FROM )
AND ( #ASSET_NO_TO = '' OR u.ASSET_NO <= #ASSET_NO_TO )
AND ( #FUND_CD = '' OR PM_FUND_CD in ( SELECT FUND_CD from #fundcode ))
AND ( #FUND_CD_FROM = '' OR fin.PM_FUND_CD >= #FUND_CD_FROM )
AND ( #FUND_CD_TO = '' OR fin.PM_FUND_CD <= #FUND_CD_TO )
AND ( #UNITPRICE_FROM is null OR fin.UNIT_COST >= #UNITPRICE_FROM )
AND ( #UNITPRICE_TO is null OR fin.UNIT_COST <= #UNITPRICE_TO )
AND ( #CAPITALIZED is null OR fin.CAPITALIZED = #CAPITALIZED )
END -- proc
I'm at a loss now. Seems there is simply too much data to process on too small a server.
The modifications are:
1) create a new scalar function to test if data exist in delimited comma text and no need to create #temp tables to check if data exist.
-- test if token exis in delimited comma string, use spli function
create FUNCTION [dbo].[inList]
(
#delimited NVARCHAR(MAX) ,
#token NVARCHAR(100)
)
RETURNS NVARCHAR(100)
as
begin
declare #retval NVARCHAR(100)
select #retval=data from
dbo.split(#delimited) t
where t.data=#token
return #retval
end
go
we replace the expression in where condition, as in the following example:
-- AND ( #ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))
modified to:
AND ( #ASSET_NO = '' OR u.ASSET_NO = dbo.inlist(#ASSET_NO,u.ASSET_NO))
and the same for all delimited lists
2) As you use many null parameters, recompile SP before execution to get fresh execution plan ( WITH RECOMPILE)
3) The modified code:
Alter PROCEDURE [dbo].[rpt_Registrations_Std]
#Action nvarchar(50) = '', -- Action is field name for now
#DATE_OPRT_FROM datetime = null,
#DATE_OPRT_TO datetime = null,
#DATE_EFFECTIVE_FROM datetime = null,
#DATE_EFFECTIVE_TO datetime = null,
#DATE_MODIFIED_FROM datetime = null,
#DATE_MODIFIED_TO datetime = null,
#ASSET_NO nvarchar(4000) = '',
#ASSET_NO_FROM nvarchar(20) = '',
#ASSET_NO_TO nvarchar(20) = '',
#HOLDER_CD nvarchar(4000) = '',
#HOLDER_CD_FROM nvarchar(10) = '',
#HOLDER_CD_TO nvarchar(10) = '',
#SITE_CD nvarchar(4000) = '',
#SITE_CD_FROM nvarchar(10) = '',
#SITE_CD_TO nvarchar(10) = '',
#ASSETCODE nvarchar(4000) = '',
#ASSETCODE_FROM nvarchar(10) = null,
#ASSETCODE_TO nvarchar(10) = null,
#FUND_CD nvarchar(4000) = '',
#FUND_CD_FROM nvarchar(10) = '',
#FUND_CD_TO nvarchar(10) = '',
#PO_NO nvarchar(4000) = '',
#PO_NO_FROM nvarchar(15) = '',
#PO_NO_TO nvarchar(15) = '',
#STATUS nvarchar(4000) = '',
#STATUS_FROM int = null,
#STATUS_TO int = null,
#UNITPRICE_FROM money = null,
#UNITPRICE_TO money = null,
#CAPITALIZED bit = Null
-- hint recompile for new fresh execution plan
WITH RECOMPILE
AS
BEGIN
--select cast(data as nvarchar) ASSET_NO INTO #asset_nos from dbo.split(#ASSET_NO,',')
-- where data is not null
--select cast(data as nvarchar) HOLDER_CD INTO #holders from dbo.split(#HOLDER_CD,',')
-- where data is not null
--select cast(data as nvarchar) SITE_CD INTO #site from dbo.split(#SITE_CD,',')
-- where data is not null
--select cast(data as nvarchar) ASSETCODE INTO #assetcode from dbo.split(#ASSETCODE,',')
-- where data is not null
--select cast(data as nvarchar) FUND_CD INTO #fundcode from dbo.split(#FUND_CD,',')
-- where data is not null
--select cast(data as nvarchar) PO_NO INTO #pono from dbo.split(#PO_NO,',')
-- where data is not null
--select cast(data as int) [STATUS] INTO #status from dbo.split(#STATUS,',')
-- where data is not null
DECLARE #FIELD nvarchar(20)
SET #FIELD = #Action
--- FIELD Def for report From here
SELECT
a.ASSET_NO
,a.DATE_RECEIVED as DATE_OPRT
,a.DATE_EFFECTIVE_REGISTERED as DATE_EFFECTIVE
,a.DATE_REGISTERED as DATE_MODIFIED
,a.USER_ID_REGIST as USER_ID_MODIFY
,a.DESC_1
,a.DESC_2
,a.DESC_AX
,a.DESC_1
+ CASE WHEN IsNull(a.DESC_2, '') = '' THEN '' ELSE ' ' + a.DESC_2 END
+ CASE WHEN IsNull(a.DESC_AX, '') = '' THEN '' ELSE ' ' + a.DESC_AX END
as ASSET_DESC
,a.MANUFACTURER
,a.MODEL
,a.SERIAL_NO
,a.WEIGHT
,a.ASSETCODE
,a.SITE_CD
,a.ROOM_CD
,a.BUILDING_CD
,a.HOLDER_CD
,a.HOLDER_DESC
,a.STATUS
,Left(a.STATUS_DESC, 10) as STATUS_DESC
,ac.CODE_DESCRIPTION
,a.RM_DESC_1 AS ROOM_DESC
,a.SITE_NAME_1 AS SITE_NAME
,a.BUILDING_NAME
,a.DATE_RECEIVED
,fin.DATE_INSERVICE
,fin.ORIG_COST
,fin.QTY
,fin.PM_FUND_CD as FUND_CD
,fin.CAPITALIZED
,fnd.FUND_DESC
,a.PM_PO_NO as PO_NO
-- Initial values
,u.ORIG_COST AS INIT_COST
,ui.ASSETCODE AS INIT_ASSETCODE
,uR.SITE_CD AS INIT_SITE_CD
,u.ROOM_CD AS INIT_ROOM_CD
,uR.BUILDING_CD AS INIT_BUILDING_CD
,uR.RM_DESC_1 AS INIT_ROOM_DESC
,uR.BUILDING_NAME AS INIT_BUILDING_NAME
,uR.SITE_NAME_1 AS INIT_SITE_NAME
,u.HOLDER_CD AS INIT_HOLDER_CD
,uH.ORG_DESC AS INIT_HOLDER_DESC
,uac.CODE_DESCRIPTION AS INIT_CODE_DESCRIPTION
FROM vAsset as a
LEFT JOIN vAsset_Rgst_Info as u ON a.ASSET_ID = u.ASSET_ID
LEFT JOIN tAssetCode as ac ON a.ASSETCODE = ac.ASSETCODE
LEFT JOIN tAssetFin as fin ON a.ASSET_NO = fin.ASSET_NO
LEFT JOIN tFunding as fnd ON fin.PM_FUND_CD = fnd.FUND_CD
LEFT JOIN tItemCatalog as ui ON u.ITEM_CD = ui.ITEM_CD
LEFT jOIN tAssetCode as uac ON ui.ASSETCODE = uac.ASSETCODE
LEFT JOIN vRoom as uR ON u.ROOM_CD = uR.ROOM_CD
LEFT JOIN tOrganization as uH ON u.HOLDER_CD = uH.ORG_CD
WHERE
( #DATE_OPRT_FROM is null OR a.DATE_RECEIVED >= #DATE_OPRT_FROM )
AND ( #DATE_OPRT_TO is null OR a.DATE_RECEIVED <= #DATE_OPRT_TO )
AND ( #DATE_EFFECTIVE_FROM is null OR a.DATE_EFFECTIVE_REGISTERED >= #DATE_EFFECTIVE_FROM )
AND ( #DATE_EFFECTIVE_TO is null OR a.DATE_EFFECTIVE_REGISTERED <= #DATE_EFFECTIVE_TO )
AND ( #DATE_MODIFIED_FROM is null OR a.DATE_REGISTERED >= #DATE_MODIFIED_FROM )
AND ( #DATE_MODIFIED_TO is null OR a.DATE_REGISTERED <= #DATE_MODIFIED_TO )
-- AND ( #ASSET_NO = '' OR u.ASSET_NO in ( SELECT ASSET_NO from #asset_nos ))
AND ( #ASSET_NO = '' OR u.ASSET_NO = dbo.inlist(#ASSET_NO,u.ASSET_NO))
AND ( #ASSET_NO_FROM = '' OR u.ASSET_NO >= #ASSET_NO_FROM )
AND ( #ASSET_NO_TO = '' OR u.ASSET_NO <= #ASSET_NO_TO )
-- AND ( #HOLDER_CD = '' OR a.HOLDER_CD in ( SELECT HOLDER_CD from #holders ))
AND ( #HOLDER_CD = '' OR a.HOLDER_CD =dbo.inlist(#HOLDER_CD,a.HOLDER_CD))
AND ( #HOLDER_CD_FROM = '' OR a.HOLDER_CD >= #HOLDER_CD_FROM )
AND ( #HOLDER_CD_TO = '' OR a.HOLDER_CD <= #HOLDER_CD_TO )
-- AND ( #SITE_CD = '' OR a.SITE_CD in ( SELECT SITE_CD from #site ))
AND ( #SITE_CD = '' OR a.SITE_CD =dbo.inlist(#SITE_CD,a.SITE_CD))
AND ( #SITE_CD_FROM = '' OR a.SITE_CD >= #SITE_CD_FROM )
AND ( #SITE_CD_TO = '' OR a.SITE_CD <= #SITE_CD_TO )
-- AND ( #ASSETCODE = '' OR a.ASSETCODE in ( SELECT ASSETCODE from #assetcode ))
AND ( #ASSETCODE = '' OR a.ASSETCODE =dbo.inlist(#ASSETCODE,a.ASSETCODE))
AND ( #ASSETCODE_FROM is null OR a.ASSETCODE >= #ASSETCODE_FROM )
AND ( #ASSETCODE_TO is null OR a.ASSETCODE <= #ASSETCODE_TO )
-- PM_FUND_CD qualified by a.PM_FUND_CD
--AND ( #FUND_CD = '' OR PM_FUND_CD in ( SELECT FUND_CD from #fundcode ))
AND ( #FUND_CD = '' OR a.PM_FUND_CD =dbo.inlist(#FUND_CD,a.PM_FUND_CD))
AND ( #FUND_CD_FROM = '' OR fin.PM_FUND_CD >= #FUND_CD_FROM )
AND ( #FUND_CD_TO = '' OR fin.PM_FUND_CD <= #FUND_CD_TO )
-- AND ( #PO_NO = '' OR a.PM_PO_NO in ( SELECT PO_NO from #pono ))
AND ( #PO_NO = '' OR a.PM_PO_NO =dbo.inlist(#PO_NO,a.PM_PO_NO))
AND ( #PO_NO_FROM = '' OR a.PM_PO_NO >= #PO_NO_FROM )
AND ( #PO_NO_TO = '' OR a.PM_PO_NO <= #PO_NO_TO )
-- AND ( #STATUS = '' OR a.STATUS in ( SELECT [STATUS] from #status ))
AND ( #STATUS = '' OR a.STATUS =dbo.inlist(#STATUS,a.STATUS))
AND ( #STATUS_FROM is null OR a.STATUS >= #STATUS_FROM )
AND ( #STATUS_TO is null OR a.STATUS <= #STATUS_TO )
AND ( #UNITPRICE_FROM is null OR fin.UNIT_COST >= #UNITPRICE_FROM )
AND ( #UNITPRICE_TO is null OR fin.UNIT_COST <= #UNITPRICE_TO )
AND ( #CAPITALIZED is null OR fin.CAPITALIZED = #CAPITALIZED )
END -- proc
go
Update:
Based on the comments that
"What you have described will not work in a stored procedure because the parameter values are not known ahead of time."
The parameter values are really known a head of time,because they are received in the stored procedure header. The scalar function is executed in time of call and return value or null based on the passed parameters of the SP.
for example: The snippet code
AND ( #ASSETCODE = '' OR a.ASSETCODE =dbo.inlist(#ASSETCODE,a.ASSETCODE))
#ASSETCODE is a parameter value (delimited list )
a.ASSETCODE is the value of the current row
so, this expression is evaluated in time and return true/false
The same for the other six lists used in OP
The following test case simulate the use of the scalar function {inlist} as used in my answer:
create procedure test_delimeted_list (
#list1 nvarchar(100)
)
as
begin
select * from products p
where p.ProductID = dbo.[inList](#list1,p.productid)
end
go
Test1: list has a value
exec test_delimeted_list '2,500,610' -- 2 is existing
The return data from northwind database :
ProductID ProductName SupplierID CategoryID QuantityPerUnit UnitPrice UnitsInStock UnitsOnOrder ReorderLevel Discontinued
2 Chang 1 1 24 - 12 oz bottles 19.00 17 40 25 0
Test2: list is null
exec test_delimeted_list null
The return data is null
I hope the OP test my code and provide comments for something missing or not working.
There is lot of scope of improving your query .
i) From DBA point of view : you need to understand table structure .
ii) Query can also be improve :If business logic and table purpose is clear.
BTW,Alter proc is more confusing .
I am only talking about very genral thing.
Improvement no. 1 : Instead of so many passing comma seperated value.you can create single Table type with as many columns and pass it as parameter.Then you can directly join them in your query. This is one time effort,but will save so many query in your proc.
Improvement 2 : Are you sure about so may Left join.Can we convert some into Inner join ?
Improvement 3 : There is no pagination.Are you trying to pull million of records?
Improvement 4 :For Example,#UNITPRICE_FROM is not null then is it possible that #UNITPRICE_TO is null.
Improvment No 5 : Some of your parameter and there use in where condition suggest that,data type are wrongly implemently,like
#ASSET_NO nvarchar(4000) = '', #ASSET_NO_FROM nvarchar(20) = ''
As far as I know > or < operator best suited for int or datetime type.
I am coming to #FranciscoGoldenstein point of view but lets make few thing clear and improve few thing.
Now let me hear from you.

Join unique ID's from another table

Here is the story: I have to implement filter. And in this filter there are certain categories I filter by.
One of the filters is "favourite" filter (#includeFavourites ).
I have this huge SQL with paging and sorting and everything.
Now, when "includeFavourites" option in filter is clicked, then I also have to select unique ID's from different table (this entries are stored in different datatable), where favourites are stored.
I have tried left outer join, but it returns "number of favourites" records for each record in primary table. Coalesce didn't help at all.
Here is my SQL:
--this is needed because stored procedure must know how many days are selected
DECLARE #daysCount int
SET #daysCount = 0
IF (#mon IS NOT NULL)
BEGIN
SET #daysCount = #daysCount+1
END
IF (#tue IS NOT NULL)
BEGIN
SET #daysCount = #daysCount+1
END
IF (#wed IS NOT NULL)
BEGIN
SET #daysCount = #daysCount+1
END
IF (#thu IS NOT NULL)
BEGIN
SET #daysCount = #daysCount+1
END
IF (#fri IS NOT NULL)
BEGIN
SET #daysCount = #daysCount+1
END
IF (#sat IS NOT NULL)
BEGIN
SET #daysCount = #daysCount+1
END
IF (#sun IS NOT NULL)
BEGIN
SET #daysCount = #daysCount+1
END
-- Insert statements for procedure here
SELECT * FROM (
SELECT ROW_NUMBER() OVER
(
ORDER BY
CASE WHEN #OrderBy = 'ND' THEN title END DESC,
CASE WHEN #OrderBy = 'NA' THEN title END,
CASE WHEN #OrderBy = '' THEN title END,
CASE WHEN #OrderBy = 'RD' THEN authorRating END DESC,
CASE WHEN #OrderBy = 'RA' THEN authorRating
) AS Row,
Articles.ArticleId, Articles.userId, Articles.timestamp as datePosted, users.screenName,
defaultSmallImagePath, authorRating, ArticleCosts, title,
FROM Articles
LEFT OUTER JOIN
Users on Articles.userId = Users.userId
LEFT OUTER JOIN
ArticleAdditionalInformation ON ArticleAdditionalInformation.ArticleId = Articles.ArticleId
--JOIN FOR CONTINENT
LEFT OUTER JOIN
Codings as Continent ON Continent.codingKeyId = ArticleAdditionalInformation.continentId AND Continent.languageId = #languageId
-- JOIN FOR COUNTRY
LEFT OUTER JOIN
CodingsAssociated as Country ON Country.codingKeyId = ArticleAdditionalInformation.countryId AND Country.languageId = #languageId
-- JOIN FOR Article TRANSLATION DATA
LEFT OUTER JOIN
ArticlesTranslations ON ArticlesTranslations.ArticleId = Articles.ArticleId AND ArticlesTranslations.languageId=#languageId
LEFT OUTER JOIN
ArticleCategories ON ArticleCategories.ArticleId = Articles.ArticleId
WHERE
(
ArticleCategories.categorieId =1 OR ArticleCategories.categorieId =2 OR
ArticleCategories.categorieId =3 OR ArticleCategories.categorieId =4 OR
ArticleCategories.categorieId = 5
) AND
(ArticlesTranslations.title LIKE '%' + #searchString + '%' OR #searchString IS NULL)
-- COST filter
AND
(ArticleCosts < #cost OR #cost = 0)
AND
(ArticleCosts > 0 OR #cost = 0)
--END cost filter
-- EXCLUDE already stored for selected days
AND Articles.ArticleId -- exclude these ArticleIds
NOT IN
(
SELECT DailyContent.ArticleId
FROM DailyContent
WHERE
sectionId=#sectionId AND
(
weekDayId=#mon OR
weekDayId=#tue OR
weekDayId=#wed OR
weekDayId=#thu OR
weekDayId=#fri OR
weekDayId=#sat OR
weekDayId=#sun
)
GROUP BY
DailyContent.ArticleId
HAVING
(COUNT(sectionId) = #daysCount)
)
-- END exclude
) p
WHERE (Row > #startRowIndex AND Row <=#startRowIndex + #pageSize)
ORDER BY Row
END
So, I would only like to include unique articleIds from favourite table, when #includeFavourites parameter is not null.
Any hint would be greatly appreciated ;)
I am using SQL server 2008.
Try this one -
DECLARE #daysCount INT
SELECT #daysCount =
ISNULL(#mon, 0) + -- if #mon = 1, #tue = 2, .... 1 + (2-1)=1 + (3-2)=1 + ...
ISNULL(#tue - 1, 0) +
ISNULL(#wed - 2, 0) +
ISNULL(#thu - 3, 0) +
ISNULL(#fri - 4, 0) +
ISNULL(#sat - 5, 0) +
ISNULL(#sun - 6, 0)
SELECT *
FROM (
SELECT ROW_NUMBER() OVER
(
ORDER BY
CASE WHEN #OrderBy = 'ND' THEN title END DESC,
CASE WHEN #OrderBy IN ('NA', '') THEN title END,
CASE WHEN #OrderBy = 'RD' THEN authorRating END DESC,
CASE WHEN #OrderBy = 'RA' THEN authorRating
) AS [Row]
, a.ArticleId
, a.userId
, a.[timestamp] as datePosted
, u.screenName
, defaultSmallImagePath
, authorRating
, ArticleCosts
, title
FROM dbo.Articles a -- always use schema and alias
LEFT JOIN dbo.Users u on a.userId = u.userId -- OUTER is unnecessary
LEFT JOIN dbo.ArticleAdditionalInformation aai ON aai.ArticleId = a.ArticleId
LEFT JOIN dbo.Codings cd ON cd.codingKeyId = aai.continentId AND cd.languageId = #languageId
LEFT JOIN dbo.CodingsAssociated c ON c.codingKeyId = aai.countryId AND c.languageId = #languageId
LEFT JOIN dbo.ArticlesTranslations at ON at.ArticleId = a.ArticleId AND at.languageId = #languageId
LEFT JOIN dbo.ArticleCategories ac ON ac.ArticleId = a.ArticleId
WHERE ac.categorieId IN (1, 2, 3, 4, 5)
AND (
at.title LIKE '%' + #searchString + '%'
OR
#searchString IS NULL
)
AND (ArticleCosts < #cost OR #cost = 0)
AND (ArticleCosts > 0 OR #cost = 0)
AND a.ArticleId NOT IN (
SELECT dc2.ArticleId
FROM dbo.DailyContent dc2
WHERE sectionId = #sectionId
AND (
weekDayId % #daysCount = 0 -- possible it's works
--weekDayId = #mon OR
--weekDayId = #tue OR
--weekDayId = #wed OR
--weekDayId = #thu OR
--weekDayId = #fri OR
--weekDayId = #sat OR
--weekDayId = #sun
)
GROUP BY dc2.ArticleId
HAVING COUNT(sectionId) = #daysCount
)
) p
WHERE [Row] BETWEEN #startRowIndex AND #startRowIndex + #pageSize
--ORDER BY [Row] -- ROW_COUNT already sorted your rows