Parameterized stored procedure union all which is conditional with left joins - sql
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
Related
BizTalk 2013R2 SQL Query Timeouts
Using BizTalk to call a SQL Server stored procedure (see below), which: Writes data to 5 tables Checks each table to see if the record exists Updates or Inserts accordingly The problem is that when BizTalk receives hundreds of calls, the stored procedure is called each time which appears to add an overhead to the SQL Server and eventually causes timeout errors returned in BizTalk, resulting in the data not being written to the database. Can anyone advise on the best way to optimise my query so that it processes these tables without much overhead, or have I got it optimised enough already? USE [MDH] GO /****** Object: StoredProcedure [dbo].[spcuPersonStudentProgrammeModule] Script Date: 8/15/2022 2:29:04 PM ******/ SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [dbo].[spcuPersonStudentProgrammeModule] -- person/personref params #student_id VARCHAR(max) ,#account_id VARCHAR(max) = NULL ,#prefix_honorific VARCHAR(max) = NULL ,#first_name VARCHAR(max) = NULL ,#middle_name VARCHAR(max) = NULL ,#surname VARCHAR(max) = NULL ,#familiar_name VARCHAR(max) = NULL ,#date_of_birth DATE = NULL ,#external_email_address VARCHAR(max) = NULL ,#mobile_phone_no VARCHAR(max) = NULL ,#gender VARCHAR(max) = NULL ,#ethnicity VARCHAR(max) = NULL ,#domicile VARCHAR(max) = NULL ,#disability VARCHAR(max) = NULL ,#nationality VARCHAR(max) = NULL ,#telephone_no VARCHAR(max) = NULL ,#prev_surname VARCHAR(max) = NULL ,#country_of_birth VARCHAR(max) = NULL -- student params ,#student_email_address VARCHAR(max) = NULL ,#currently_studying_flag VARCHAR(max) = NULL ,#HesaStudentID VARCHAR(max) = NULL ,#UCAS_ID VARCHAR(max) = NULL ,#uln VARCHAR(max) = NULL ,#VisaReq VARCHAR(max) = NULL ,#PurposeOfResidency VARCHAR(max) = NULL ,#cas_status VARCHAR(max) = NULL ,#student_status VARCHAR(max) = NULL ,#source_system VARCHAR(max) = NULL ,#main_programme_code VARCHAR(max) = NULL ,#type VARCHAR(max) = NULL ,#student_support_no VARCHAR(max) = NULL ,#exam_id VARCHAR(max) = NULL ,#su_opt VARCHAR(max) = NULL ,#change_type VARCHAR(max) = NULL ,#international_sponsored_students varchar(80) = null ,#visa_type VARCHAR(max) = null -- student_programmes params ,#programme_code VARCHAR(50) ,#programme_description VARCHAR(MAX) = NULL ,#start_date DATETIME = NULL ,#end_date DATETIME = NULL ,#mdh_stage_code VARCHAR(MAX) = NULL ,#main_award_flag VARCHAR(10) = NULL ,#load_category VARCHAR(10) = NULL ,#qualification_level VARCHAR(10) = NULL ,#student_study_level VARCHAR(10) = NULL ,#school_code VARCHAR(10) = NULL ,#college_code VARCHAR(10) = NULL ,#campus_code VARCHAR(10) = NULL ,#graduate_yn VARCHAR(10) = NULL ,#is_wbdl VARCHAR(80) = NULL ,#ul_qual_aim VARCHAR(MAX) = NULL ,#ul_qual_aim_desc VARCHAR(MAX) = NULL -- student_modules params ,#module_code VARCHAR(50) ,#module_desc VARCHAR(MAX) = NULL ,#mod_date_time DATETIME = NULL -- student_address params ,#perm_address1 VARCHAR(50) = NULL ,#perm_address2 VARCHAR(50) = NULL ,#perm_address3 VARCHAR(50) = NULL ,#perm_address4 VARCHAR(50) = NULL ,#perm_address5 VARCHAR(50) = NULL ,#perm_postcode VARCHAR(50) = NULL ,#perm_country_code VARCHAR(50) = NULL ,#term_address1 VARCHAR(50) = NULL ,#term_address2 VARCHAR(50) = NULL ,#term_address3 VARCHAR(50) = NULL ,#term_address4 VARCHAR(50) = NULL ,#term_address5 VARCHAR(50) = NULL ,#term_postcode VARCHAR(50) = NULL ,#term_country_code VARCHAR(50) = NULL AS BEGIN -- SET NOCOUNT ON added to prevent extra result sets from -- interfering with SELECT statements. DECLARE #person_id UNIQUEIDENTIFIER SET NOCOUNT ON; SET TRANSACTION ISOLATION LEVEL READ COMMITTED -- Create/Update person_test/person_reference_test IF EXISTS ( SELECT person_id FROM dbo.person_reference WHERE account_id = #account_id and ISNULL(status,'') <> 'Delete') BEGIN SELECT 'Student exists, updating' SET #person_id = ( SELECT person_id FROM dbo.person_reference WITH (NOLOCK) WHERE account_id = #account_id and ISNULL(status,'') <> 'Delete') UPDATE person SET prefix_honorific = CASE WHEN #prefix_honorific = 'null' or #prefix_honorific is null or #prefix_honorific = '' THEN prefix_honorific ELSE #prefix_honorific END ,first_name = ISNULL(#first_name, first_name) ,middle_name = ISNULL(#middle_name, middle_name) ,surname = ISNULL(#surname, surname) ,familiar_name = #familiar_name ,date_of_birth = ISNULL(#date_of_birth, date_of_birth) ,external_email_address = ISNULL(#external_email_address, external_email_address) ,gender = ISNULL(#gender, gender) ,ethnicity = ISNULL(#ethnicity, ethnicity) ,domicile = ISNULL(#domicile, domicile) ,disability = ISNULL(#telephone_no, disability) ,telephone_no = ISNULL(#telephone_no, telephone_no) ,prev_surname = ISNULL(#prev_surname, prev_surname) ,country_of_birth = ISNULL(#country_of_birth, country_of_birth) ,proc_date_time = GETDATE() ,mobile_phone_no = ISNULL(#mobile_phone_no, mobile_phone_no) ,nationality = ISNULL(#nationality, nationality) WHERE person_id_guid = #person_id IF #account_id IS NOT NULL BEGIN UPDATE dbo.person_reference SET account_id = #account_id ,proc_date_time = GETDATE() WHERE person_id = #person_id END END ELSE BEGIN SELECT 'Student does not exist, creating' --INSERT person SET #person_id = NEWID() INSERT INTO dbo.person ( person_id_guid ,prefix_honorific ,first_name ,middle_name ,surname ,familiar_name ,date_of_birth ,external_email_address ,mobile_phone_no ,gender ,ethnicity ,domicile ,disability ,nationality ,telephone_no ,prev_surname ,country_of_birth ,source_system ,proc_date_time ) VALUES ( #person_id ,#prefix_honorific ,#first_name ,#middle_name ,#surname ,#familiar_name ,#date_of_birth ,#external_email_address ,#mobile_phone_no ,#gender ,#ethnicity ,#domicile ,#disability ,#nationality ,#telephone_no ,#prev_surname ,'OneUni' ,#country_of_birth ,GETDATE() ) --INSERT person_reference INSERT INTO dbo.person_reference ( person_id ,student_id ,proc_date_time ,account_id ) VALUES ( #person_id ,#student_id ,GETDATE() ,#account_id ) END -- Create/Update student IF EXISTS ( SELECT account_id FROM dbo.student WITH (NOLOCK) WHERE account_id = #account_id and ISNULL(status,'') <> 'Delete') BEGIN SELECT 'Student exists, updating' UPDATE student SET --account_id = #account_id --,student_id = #student_id ucas_id = #UCAS_ID ,unique_learner_number = #uln ,main_programme_code = isnull(#main_programme_code, main_programme_code) ,student_email_address = #student_email_address ,currently_studying_flag = #currently_studying_flag ,hesa_student_id = #HesaStudentID ,visa_required = #VisaReq ,cas_status = #cas_status ,student_status = #student_status ,purpose_of_residency = #PurposeOfResidency ,mod_date_time = GETDATE() ,student_support_no = #student_support_no ,source_system = #source_system ,exam_id = #exam_id ,su_opt = #su_opt ,international_sponsored_students = #international_sponsored_students ,visa_type = #visa_type WHERE account_id = #account_id END -- Create Student/Student Programme/Student Module ELSE BEGIN SELECT 'Student does not exist, creating' SET #person_id = ( SELECT person_id FROM dbo.person_reference WITH (NOLOCK) WHERE account_id = #account_id and ISNULL(status,'') <> 'Delete') INSERT INTO student ( person_id_guid ,account_id ,ucas_id ,unique_learner_number ,student_email_address ,currently_studying_flag ,hesa_student_id ,visa_required ,cas_status ,student_status ,purpose_of_residency ,proc_date_time ,source_system ,main_programme_code ,student_id ,student_support_no ,exam_id ,su_opt ,international_sponsored_students ,visa_type ) VALUES ( #person_id ,#account_id ,#UCAS_ID ,#uln ,#student_email_address ,#currently_studying_flag ,#HesaStudentID ,#VisaReq ,#cas_status ,#student_status ,#PurposeOfResidency ,getdate() ,#source_system ,#main_programme_code ,#student_id ,#student_support_no ,#exam_id ,#su_opt ,#international_sponsored_students ,#visa_type ) END -- Create/Update student_programmes if change_record is 'Course' IF #change_type = 'Programme' BEGIN -- Create/Update student_programmes IF EXISTS ( SELECT student_id FROM student_programmes WITH (NOLOCK) WHERE account_id = #account_id and programme_code = #programme_code) BEGIN SELECT 'Student Programme exists, updating' --UPDATE student_programme? (Wait for confirmation) UPDATE student_programmes SET --account_id = #account_id --,student_id = #student_id --course_code = #course_code programme_description = #programme_description ,[start_date] = #start_date ,end_date = #end_date ,mdh_stage_code = #mdh_stage_code ,main_award_flag = #main_award_flag ,load_category = #load_category ,qualification_level = #qualification_level ,student_study_level = #student_study_level ,is_wbdl = #is_wbdl ,school_code = #school_code ,college_code = #college_code ,campus_code = #campus_code ,ul_qual_aim = #ul_qual_aim ,ul_qual_aim_description = #ul_qual_aim_desc ,mod_date_time = GETDATE() WHERE account_id = #account_id and programme_code = #programme_code END ELSE BEGIN SELECT 'Student Programme does not exist, creating' SET #person_id = ( SELECT person_id FROM dbo.person_reference WITH (NOLOCK) WHERE account_id = #account_id and ISNULL(status,'') <> 'Delete') --INSERT student_programme INSERT INTO student_programmes ( person_id_guid ,account_id ,student_id ,programme_code ,programme_description ,[start_date] ,end_date ,mdh_stage_code ,main_award_flag ,load_category ,qualification_level ,student_study_level ,is_wbdl ,school_code ,college_code ,campus_code ,ul_qual_aim ,ul_qual_aim_description ,mod_date_time ) VALUES ( #person_id ,#account_id ,#student_id ,#programme_code ,#programme_description ,#start_date ,#end_date ,#mdh_stage_code ,#main_award_flag ,#load_category ,#qualification_level ,#student_study_level ,#is_wbdl ,#school_code ,#college_code ,#campus_code ,#ul_qual_aim ,#ul_qual_aim_desc ,GETDATE() ) END END -- Create/Update student_modules if change_record is 'Module' IF #change_type = 'Module' BEGIN IF EXISTS ( SELECT student_id FROM student_modules WITH (NOLOCK) WHERE account_id = #account_id and programme_code = #programme_code and module_code = #module_code) BEGIN SELECT 'Student Module exists, updating' --UPDATE student_module? (Wait for confirmation) UPDATE student_modules SET --account_id = #account_id --,student_id = #student_id --course_code = #course_code --module_code = #module_code module_description = #module_desc ,mdh_stage_code = #mdh_stage_code ,student_study_level = #student_study_level ,mod_date_time = GETDATE() WHERE account_id = #account_id and programme_code = #programme_code and module_code = #module_code END ELSE BEGIN SELECT 'Student Module does not exist, creating' SET #person_id = ( SELECT person_id FROM dbo.person_reference WITH (NOLOCK) WHERE account_id = #account_id and ISNULL(status,'') <> 'Delete') -- If the programme for the module/student doesnt exist, insert it IF NOT EXISTS ( SELECT student_id FROM dbo.student_programmes WITH (NOLOCK) WHERE account_id = #account_id and programme_code = #programme_code) BEGIN SET #person_id = ( SELECT person_id FROM dbo.person_reference WITH (NOLOCK) WHERE account_id = #account_id ) --INSERT student_programme INSERT INTO student_programmes ( person_id_guid ,account_id ,student_id ,programme_code ,programme_description ,[start_date] ,end_date ,mdh_stage_code ,main_award_flag ,load_category ,qualification_level ,student_study_level ,is_wbdl ,school_code ,college_code ,campus_code ,ul_qual_aim ,ul_qual_aim_description ,mod_date_time ) VALUES ( #person_id ,#account_id ,#student_id ,#programme_code ,#programme_description ,#start_date ,#end_date ,#mdh_stage_code ,#main_award_flag ,#load_category ,#qualification_level ,#student_study_level ,#is_wbdl ,#school_code ,#college_code ,#campus_code ,#ul_qual_aim ,#ul_qual_aim_desc ,GETDATE() ) END --INSERT student_module INSERT INTO student_modules ( person_id_guid ,account_id ,student_id ,programme_code ,module_code ,module_description ,mdh_stage_code ,student_study_level ,mod_date_time ) VALUES ( #person_id ,#account_id ,#student_id ,#programme_code ,#module_code ,#module_desc ,#mdh_stage_code ,#student_study_level ,GETDATE() ) END END END
Where clause filter in stored procedure
I'm trying to create a procedure where it needs to filter the records with where condition by multiple scalar parameters. I'm facing the problem with the column I.[status]. In that column the values will be as "pending", "rejected", "submitted". But when the value comes with "All", I need to select all the status types (pending, rejected, submitted) CREATE PROCEDURE [dbo].[sp_cc_get_Invoices] (#po_id INT = NULL, #sortBy VARCHAR(50) = NULL, #sortDirection VARCHAR(50) = 0, #pageSize INT = NULL, #page INT = NULL, #TotalRows INT = NULL OUTPUT, #time_zone_offset INT = 0, #vendor_id VARCHAR(MAX) = NULL, #status VARCHAR(20) = 'All', #invoice_id INT = NULL, #invoice_from_dt DATETIME2 = NULL, #invoice_to_dt DATETIME2 = NULL) AS BEGIN SELECT I.invoice_id, I.invoice_amount, I.[status], v.vendor_id, I.po_id, v.vendor_name, I.netsuit_invoice_id, cd.currency_symbol FROM invoice_details I LEFT JOIN vendor_details v ON v.vendor_id = I.vendor_id LEFT JOIN currency_details cd ON cd.currency_id = I.currency_id WHERE (#po_id IS NULL OR I.po_id = #po_id) AND (#vendor_id IS NULL OR I.vendor_id = #vendor_id) AND (#invoice_id IS NULL OR #invoice_id = '' OR I.invoice_id = #invoice_id) AND (I.invoice_date BETWEEN #invoice_from_dt AND #invoice_to_dt) AND I.[status] = #status END How to filter all the status records?
You can express this with boolean logic. Just change: and I.[status] = #status To: and (#status = 'All' or I.[status] = #status)
Procedure inserts only one record
I have this stored procedure: CREATE PROCEDURE [dbo].[TVP_OfferPrice] #OfferPriceTVP TVP_OfferPrice READONLY AS BEGIN DECLARE #OfferId INT; DECLARE #CountryId INT ; DECLARE #VatRateId INT ; DECLARE #SalePrice DECIMAL(16, 4) ; DECLARE #SaleFromDate DATETIME; DECLARE #SaleToDate DATETIME; DECLARE #DefaultPrice DECIMAL(16, 4); DECLARE #Price DECIMAL(16,4); SELECT #OfferId = a.OfferId, #CountryId = a.CountryId, #VatRateId = a.VatRateId, #SalePrice = a.SalePrice, #SaleFromDate = a.SaleFromDate, #SaleToDate = a.SaleToDate, #DefaultPrice =a.DefaultPrice FROM #OfferPriceTVP a; SET #Price = (SELECT TOP 1 pp.Price FROM [dbo].[Promotion] p INNER JOIN [dbo].[PromotionProduct] pp ON pp.ProductId = p.Id INNER JOIN [dbo].[Offer] do ON do.ProductId = pp.ProductId AND do.Id = #OfferId INNER JOIN [dbo].[PromotionAssignment] pda ON pda.PromotionId = p.Id AND pda.Id = do.Id WHERE p.CountryId = #CountryId AND GETUTCDATE() >= p.ValidFrom AND GETUTCDATE() < p.ValidTo ORDER BY p.ValidFrom DESC, pp.Price) IF(#Price IS NULL AND #SalePrice IS NOT NULL AND GETUTCDATE() >= #SaleFromDate AND GETUTCDATE() < #SaleFromDate) SET #Price = #SalePrice IF #Price IS NULL SET #Price = #DefaultPrice IF NOT EXISTS (SELECT * FROM [dbo].[OfferPrice] dop WHERE dop.OfferId = #OfferId AND dop.CountryId = #CountryId) INSERT INTO [dbo].[OfferPrice](OfferId, CountryId, VatRateId, Price, DefaultPrice, SalePrice, SaleFromDate, SaleToDate) SELECT #OfferId, #CountryId, #VatRateId, #Price, #DefaultPrice, #SalePrice, #SaleFromDate, #SaleToDate ELSE UPDATE b SET b.VatRateId = #VatRateId, #Price = #Price, b.DefaultPrice = #DefaultPrice, b.SalePrice = #SalePrice, b.SaleFromDate = #SaleFromDate, b.SaleToDate = #SaleToDate FROM [dbo].OfferPrice b WHERE b.OfferId = #OfferId AND b.CountryId = #CountryId; END and when I try to execute it with some values for example: DECLARE #OfferPriceTVP AS [dbo].[TVP_DealerOfferPrice] INSERT INTO #OfferPriceTVP (DealerOfferId, CountryId, VatRateId, DefaultGrossPrice, SaleGrossPrice, SaleFromDate, SaleToDate) VALUES (10006805, 1, 1, 1, 1, 2, NULL), (10006806, 1, 1, 2, 1, NULL, NULL), (10006807, 1, 1, 3, 1, NULL, NULL), (10006808, 1, 1, 4, 1, NULL, NULL), (10006809, 1, 1, 5, 1, NULL, NULL), (10006810, 1, 1, 6, 1, NULL, NULL); EXEC [dbo].[TVP_DealerOfferPrice] #OfferPriceTVP; GO SQL Server shows me that only 1 row gets affected and indeed last value gets only into my table. Any idea why?
Basically, since your variable cannot hold more than one value at the same time, with this statement: SELECT #OfferId = a.OfferId ,#CountryId = a.CountryId ,#VatRateId = a.VatRateId ,#SalePrice = a.SalePrice ,#SaleFromDate = a.SaleFromDate ,#SaleToDate = a.SaleToDate ,#DefaultPrice = a.DefaultPrice FROM #OfferPriceTVP a; you are holding only one record of your input table. I guess that you are trying to merge the input table with the OfferPrice table. So, you better use the MERGE statement. Here is an example: MERGE OfferPrice AS TARGET USING (SELECT VatRateId ,CASE WHEN Price IS NULL AND SalePrice IS NOT NULL AND GETUTCDATE() >= SaleFromDate AND GETUTCDATE() < SaleFromDate THEN SalePrice ELSE DefaultPrice END AS Price -- And so on and so forth FROM #OfferPriceTVP) AS SOURCE ON TARGET.OfferId = SOURCE.OfferId WHEN MATCHED THEN UPDATE SET VatRateId = SOURCE.VatRateId ,Price = SOURCE.Price -- And so on and so forth WHEN NOT MATCHED THEN INSERT (OfferId, CountryId) -- And so on and so forth VALUES (SOURCE.OfferId, SOURCE.CountryId) -- And so on and so forth More informations here: MERGE (Transact-SQL) CASE (Transact-SQL)
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
Improve case statement in order clause
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