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