Procedure inserts only one record - sql

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)

Related

SQL - How to Multiply Prior Row value to Current Row

Can this be done and if so what is the best approach. I tried Over(Partition) but cannot figure out how to add the prior columns. Should I use IF BEGIN ENDS and just walk through it row by row for running balance? Any assistance on initial direction would be appreciated.
CREATE TABLE [dbo].[PStatement](
[ID] [int],
[Source] [nvarchar](255),
[PaymentNumber] [int],
[PaymentAmt] [money],
[RBalance] [money],
[CBalance] [money],
[AllocationPercent] [float]
)
With the following values:
INSERT INTO PStatement (ID, [Source], PaymentNumber, PaymentAmt, RBalance, CBalance, AllocationPercent)
VALUES (1, N'SR', 1, 0, 7500, 10000, .75)
,(2, N'ER', 1, 0, 2500, 10000, .25)
,(3, N'SR', 2, 50, 0, 11000, 0)
,(4, N'ER', 2, 75, 0, 11000, .0)
,(5, N'SR', 3, 50, 0, 12000, 0)
,(6, N'ER', 3, 75, 0, 12000, .0)
I need to take the CBalance from the prior row, subtract the sum of the current rows PaymentAmt and multiple that amount by the prior rows AllocationPercentage and then add back the PaymentAmt based on PaymentNumber and Source.
So Row 3 RBalance is $11000 - ($50 + $75) (from current row) * .75 (from prior row) + 50 (from current row), AllocationPercent is RBalance/CBalance.
So Row 4 is $11000 - ($50 + $75) * .25 + 75
The end table would look like this:
You can access 'prior row' data by using something like:
select ID
, PaymentAmt
, PreviousPaymentAmt=LAG(PaymentAmt,1,0) OVER (ORDER BY ID)
from PStatement
The 2nd parameter in LAG is telling it to go only 1 record back; and the third parameter is telling it to return 0 (zero) if there are no prior rows.
Here is how I got it to work.
DECLARE #MyCursor CURSOR;
DECLARE #id INT, #Source NVARCHAR(255), #CBalance MONEY, #RBalance MONEY, #PaymentAmt MONEY, #AllocationPercent decimal(18,10), #PaymentNumber INT, #Amount MONEY;
BEGIN
SET #MyCursor = CURSOR FOR
SELECT ID FROM PStatement ORDER BY Source, PaymentNumber
OPEN #MyCursor
FETCH NEXT FROM #MyCursor
INTO #id
WHILE ##FETCH_STATUS = 0
BEGIN
SELECT #Source = Source, #PaymentNumber = PaymentNumber, #CBalance = CBalance, #PaymentAmt = PaymentAmt FROM PStatement WHERE ID = #id
IF(#PaymentNumber = 1)
BEGIN
UPDATE PStatement SET AllocationPercent = RBalance/ CAST(CBalance AS decimal(18, 10)) WHERE (ID = #id)
SET #AllocationPercent = (SELECT AllocationPercent FROM PStatement WHERE (ID = #id))
END
ELSE
BEGIN
SET #PaymentAmt = (SELECT SUM(PaymentAmt) FROM PStatement WHERE (PaymentNumber = #PaymentNumber))
SET #RBalance = ((#CBalance - #PaymentAmt) * #AllocationPercent) + #PaymentAmt
UPDATE PStatement SET RBalance = #RBalance WHERE (ID = #id)
UPDATE PStatement SET AllocationPercent = RBalance/ CAST(CBalance AS decimal(18, 10)) WHERE (ID = #id)
SET #AllocationPercent = (SELECT AllocationPercent FROM PStatement WHERE (ID = #id))
END
FETCH NEXT FROM #MyCursor
INTO #id
END;
CLOSE #MyCursor ;
DEALLOCATE #MyCursor;
END;

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 loop each record in CTE and read column values

I have to loop data in CTE and fetch each record and process based on one column value.
CREATE PROCEDURE [dbo].[sp_saveVmssMapping]
(#serverTypes INT = 0,
#vmsses INT = 0,
#regions INT = 0,
#countryList VARCHAR)
AS
WITH countryTbl AS
(
SELECT value
FROM STRING_SPLIT(#countryList, ',')
)
DECLARE #cnt INT = 0;
DECLARE #cnt_total INT;
SET #cnt_total = SELECT COUNT(*) FROM countryTbl;
WHILE #cnt < cnt_total
BEGIN
IF NOT EXISTS (SELECT * FROM VmssCountryMapping
WHERE VmssId = #vmsses
AND Country_code = #userName
AND ServerTypeId = #serverTypes)
BEGIN
INSERT INTO VmssCountryMapping (VmssId, Country_code, ServerTypeId)
VALUES (#vmsses, #userName, #serverTypes)
END
SET #cnt = #cnt + 1;
END
Here I have created a CTE where I am adding comma separated records. Now I will loop each record and process the insert if it matches the query.
There's no need to loop a result, you can simply insert everything at once.
CREATE PROCEDURE [dbo].[sp_saveVmssMapping]
(
#serverTypes INT = 0,
#vmsses INT = 0,
#regions INT = 0,
#countryList VARCHAR(AlwaysAssignALength)
)
AS
with countryTbl as
(
SELECT value FROM STRING_SPLIT(#countryList, ',')
)
INSERT INTO VmssCountryMapping (VmssId, Country_code, ServerTypeId)
SELECT #vmsses, value, #serverTypes
FROM countryTbl c
WHERE NOT EXISTS (SELECT *
FROM VmssCountryMapping m
WHERE m.VmssId = #vmsses
AND m.Country_code = c.value
AND m.ServerTypeId = #serverTypes);

Stored Procedure slowness after upgrade to SQL Server 2014

We have done a SQL Server upgrade from 2005 to 2014. Post upgrade one of the stored procedures is running very slow. It used to take about 10 mins which has now increased to 23 mins.
On further investigating, the execution time after fresh upgrade was perfectly fine and only after 3-4 executions it gets increased. I tried restoring the fresh database again and can confirm the above behaviour. Can someone help me out, since I have no clue what's happening!
I am a core DBA and not an application DBA so I don't have much knowledge about how stored procedures behave. Any help would be appreciated.
I am running using parameters :
exec [usp_RecalculateMV] '10', 8, 2015
Stored procedure code:
CREATE PROCEDURE [dbo].[usp_RecalculateMV]
(#MarketID nvarchar(100),
#FromMonth int,
#FromYear int)
AS
BEGIN
--variable to hold any errors generated by the procedure
DECLARE #ErrorCode INT
DECLARE #MarketIDs INT
DECLARE #Failed nvarchar(100)
DECLARE #SplitBy nvarchar(10)
DECLARE #StartDate nvarchar(11)
--
-- Changes done by Rupan
-- Start (SER000008289)
DECLARE #cQtytoSplit FLOAT
DECLARE #cOtherQty FLOAT
DECLARE #cSplitThreshold INT
DECLARE #cWeeklySplit NVARCHAR(35)
DECLARE #cWeeklyBufferSplit NVARCHAR(35)
DECLARE #SplitType VARCHAR(15)
DECLARE #cSplitValue FLOAT
DECLARE #jSplit INT
SET #jSplit = 1
DECLARE #iSplit INT
SET #iSplit = 1
DECLARE #cPackCode NVARCHAR(50)
DECLARE #cCustCode NVARCHAR(50)
DECLARE #Week1Cursor INT
DECLARE #Week2Cursor INT
DECLARE #Week3Cursor INT
DECLARE #Week4Cursor INT
DECLARE #QtytoSplitCursor FLOAT
DECLARE #OtherQtyCursor FLOAT
DECLARE #itemp INT
SET #itemp = 1
DECLARE #tempCount INT
DECLARE #tempPackCode NVARCHAR(50)
DECLARE #tempCustomerCode NVARCHAR(50)
DECLARE #tempWeeklyMV VARCHAR(85)
DECLARE #tempWeeklBuffer VARCHAR(85)
DECLARE #tempMVQTY FLOAT
DECLARE #tempBufferQTY FLOAT
CREATE TABLE #tmp_IntialLoad ( ID INT IDENTITY(1,1),
MVQty FLOAT,
BufferQty FLOAT,
SplitThreshold INT,
WeeklyMVQty NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS,
WeeklyBufferQty NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS,
PackCode NVARCHAR(50) COLLATE SQL_Latin1_General_CP1_CI_AS,
CustomerCode NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS
);
CREATE TABLE #tmp_SplitQTY ( ID INT IDENTITY(1,1),
SplitType VARCHAR(15) COLLATE SQL_Latin1_General_CP1_CI_AS,
QtytoSplit FLOAT,
OtherQty FLOAT,
MarketID NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
Code NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
CustomerCode NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
Week1 INT,
Week2 INT,
Week3 INT,
Week4 INT,
Week1Buffer INT,
Week2Buffer INT,
Week3Buffer INT,
Week4Buffer INT
);
CREATE TABLE #tmp_SplitBufferQTY ( ID INT IDENTITY(1,1),
SplitType VARCHAR(15) COLLATE SQL_Latin1_General_CP1_CI_AS,
QtytoSplit FLOAT,
OtherQty FLOAT,
MarketID NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
Code NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
CustomerCode NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
Week1 INT,
Week2 INT,
Week3 INT,
Week4 INT
);
CREATE TABLE #tmp_FinalSplitQTY ( ID INT IDENTITY(1,1),
MarketID NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
Code NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
CustomerCode NVARCHAR(85) COLLATE SQL_Latin1_General_CP1_CI_AS,
Week1 INT,
Week2 INT,
Week3 INT,
Week4 INT,
Week1Buffer INT,
Week2Buffer INT,
Week3Buffer INT,
Week4Buffer INT,
QtytoSplit FLOAT,
OtherQty FLOAT
);
-- END
--table struc to hold the split string passed in above
DECLARE #T_TBL_Market TABLE
(
ID INT IDENTITY(1,1),
MarketID int --nvarchar(100)
)
--populate the temporary table with the split market id's
INSERT INTO #T_TBL_Market
SELECT * FROM dbo.Split(#MarketID, ',')
SET #StartDate = dbo.GetSafeDateFormat(1, #FromMonth, #FromYear)
--create a cursor to loop through the market id's
/* Start - Rupan
DECLARE MarketCursor CURSOR FOR
SELECT MarketID FROM #T_TBL_Market
--Open
OPEN MarketCursor
--loop through the markets
FETCH NEXT FROM MarketCursor
INTO #MarketIDs
******* End */
DECLARE #iMarketID INT
SET #iMarketID = 1
DECLARE #iCount INT
SELECT #iCount = COUNT(*) FROM #T_TBL_Market
/* Start - Rupan
WHILE ##FETCH_STATUS = 0
End */
WHILE( #iMarketID <= #iCount )
BEGIN
SELECT #MarketIDs = MarketID FROM #T_TBL_Market WHERE ID = #iMarketID
Print 'Inside While'
--Changes done by Parag on 08-04-2010, inserting values for customer detail
--Deleting old values
DELETE from TBL_CUSTOMER_CODE
INSERT INTO TBL_CUSTOMER_CODE(CustomerSplitID,CustomerID, Week1Split, Week2Split, Week3Split, Week4Split, SplitThreshold, CustomerCode)
SELECT dbo.TBL_CUSTOMER_SPLIT.CustomerSplitID, dbo.TBL_CUSTOMER.CustomerID, ISNULL(dbo.TBL_CUSTOMER_SPLIT.Week1Split, 25) AS Week1Split,
ISNULL(dbo.TBL_CUSTOMER_SPLIT.Week2Split, 25) AS Week2Split, ISNULL(dbo.TBL_CUSTOMER_SPLIT.Week3Split, 25) AS Week3Split,
ISNULL(dbo.TBL_CUSTOMER_SPLIT.Week4Split, 25) AS Week4Split, dbo.TBL_CUSTOMER_SPLIT.SplitThreshold,
ISNULL(dbo.TBL_CUSTOMER.CustomerCdSoldTo, '') + ISNULL(dbo.TBL_CUSTOMER.CustomerCdShipTo, '') AS CustomerCode
FROM dbo.TBL_CUSTOMER LEFT OUTER JOIN
dbo.TBL_CUSTOMER_SPLIT ON dbo.TBL_CUSTOMER.CustomerID = dbo.TBL_CUSTOMER_SPLIT.CustomerID
WHERE TBL_CUSTOMER.marketid =#MarketIDs
--Changes end
--start a transaction to roll back if things go awry
BEGIN TRAN
--delete the data for this market including and after the startdate
Print'Before Delete'
DELETE FROM TBL_CALCULATED_MV
WHERE MarketID = #MarketIDs
AND [Month] >= #StartDate
Print'After Delete'
--check for errors
SELECT #ErrorCode = ##Error
--if no errors continue
IF #ErrorCode = 0
BEGIN
Print'Inserting into CalculatedMV table'
--do the basic recalculation of the MV and Buffer
INSERT INTO TBL_CALCULATED_MV(
MarketName, GroupDescription, MCCode,
ChannelDesc, PackCode, PackDesc, [Month],
MVQty,BufferQty,BufferPercentage,
LocalCustomerCode,LocalCustomerName,
CustomerCdSoldTo, CustomerCdShipTo,
BrandName, BrandCode,
MinMV, MarketID,
IntlCode, EPVOrgCode, AVOrgCode, LDDQty
)
SELECT DISTINCT TBL_MARKET_COMPANY.MarketName, TBL_GROUP.GroupDescription, TBL_MARKET_COMPANY.MCCode,
TBL_CHANNEL.ChannelDesc, VW_BASE_MV.PackCode, TBL_MARKET_PACK.PackDesc, VW_BASE_MV.[Month],
VW_BASE_MV.RoundedBaseMV AS MVQty,
dbo.CalculateBuffer(VW_BASE_MV.RoundedBaseMV, VW_LATEST_BUFFER.MonthValue, VW_LATEST_MINMV.MonthValue) AS BufferQty,
VW_LATEST_BUFFER.MonthValue AS BufferPercentage,
CASE WHEN TBL_CUSTOMER.CustomerCdShipTo IS NULL THEN
TBL_CUSTOMER.CustomerCdSoldTo
ELSE
TBL_CUSTOMER.CustomerCdShipTo
END AS LocalCustomerCode,
TBL_CUSTOMER.CustDescription, TBL_CUSTOMER.CustomerCdSoldTo, TBL_CUSTOMER.CustomerCdShipTo,
TBL_BRAND.BrandName, TBL_BRAND.BrandCode,
VW_LATEST_MINMV.MonthValue, VW_BASE_MV.MarketID,
TBL_MARKET_PACK.IntlCode, TBL_MARKET_COMPANY.EPVOrgCode, TBL_MARKET_COMPANY.AVOrgCode,
VW_BASE_MV.LDD
FROM TBL_CHANNEL
INNER JOIN VW_BASE_MV
ON TBL_CHANNEL.ChannelID = VW_BASE_MV.ChannelID
INNER JOIN TBL_MARKET_COMPANY
ON TBL_MARKET_COMPANY.MarketID = VW_BASE_MV.MarketID
INNER JOIN TBL_GROUP
ON TBL_GROUP.GroupID = TBL_MARKET_COMPANY.GroupID
INNER JOIN TBL_MARKET_PACK
ON VW_BASE_MV.MarketID = TBL_MARKET_PACK.MarketID
AND VW_BASE_MV.PackCode = TBL_MARKET_PACK.PackCode
INNER JOIN TBL_BRAND
ON TBL_BRAND.BrandID = TBL_MARKET_PACK.BrandID
LEFT OUTER JOIN TBL_CUSTOMER
ON VW_BASE_MV.CustomerID = TBL_CUSTOMER.CustomerID
LEFT OUTER JOIN VW_LATEST_BUFFER
ON VW_BASE_MV.MarketID = VW_LATEST_BUFFER.MarketID
AND VW_BASE_MV.PackCode = VW_LATEST_BUFFER.PackCode
AND VW_BASE_MV.ChannelID = VW_LATEST_BUFFER.ChannelID
AND VW_BASE_MV.[Month] = VW_LATEST_BUFFER.[Month]
LEFT OUTER JOIN VW_LATEST_MINMV
ON VW_BASE_MV.MarketID = VW_LATEST_MINMV.MarketID
AND VW_BASE_MV.PackCode = VW_LATEST_MINMV.PackCode
AND VW_BASE_MV.ChannelID = VW_LATEST_MINMV.ChannelID
AND VW_BASE_MV.[Month] = VW_LATEST_MINMV.[Month]
WHERE VW_BASE_MV.[Month] >= #StartDate
AND VW_BASE_MV.MarketID = #MarketIDs
AND VW_BASE_MV.RoundedBaseMV > 0
AND CASE WHEN TBL_CUSTOMER.CustomerCdShipTo IS NULL THEN
TBL_CUSTOMER.CustomerCdSoldTo
ELSE
TBL_CUSTOMER.CustomerCdShipTo
END IS NOT NULL --prevents customer still in the market share table
--but not in the customer table from being passed through
--to the calculated mv table
--check for errors
SELECT #ErrorCode = ##Error
Print 'After Inserting into CalculatedMV table'
END
IF #ErrorCode = 0 -- Start End of Errorcode 1
BEGIN
--find out if this market splits by Pack or by customer
SELECT #SplitBy = ISNULL(SplitBy, 'Unassigned')
FROM TBL_MARKET_COMPANY
WHERE MarketID = #MarketIDs
--calculate the split MV and default the SumWeeklyMV and SumWeeklyBuffer
--fields to the MV and Buffer quantities
IF ISNULL(#SplitBy, 'Unassigned') = 'Unassigned'
BEGIN
UPDATE TBL_CALCULATED_MV
SET
Week1MV = 0,
Week2MV = 0,
Week3MV = 0,
Week4MV = 0,
Week1Buffer = 0,
Week2Buffer = 0,
Week3Buffer = 0,
Week4Buffer = 0,
SumWeeklyMV = MVQty,
SumWeeklyBuffer = BufferQty,
Split = 0
WHERE
TBL_CALCULATED_MV.MarketID = #MarketIDs
AND
TBL_CALCULATED_MV.[Month] >= #StartDate
END
IF #SplitBy = 'Pack' -- Start of Pack
BEGIN
Print 'Entering Pack sum update'
UPDATE TBL_CALCULATED_MV
SET
SumWeeklyMV = MVQty,
SumWeeklyBuffer = BufferQty,
Split = CASE WHEN MP.SplitThreshold IS NULL THEN
0
WHEN MVQty + BufferQty < MP.SplitThreshold THEN
0
ELSE
1
END
FROM TBL_CALCULATED_MV
LEFT OUTER JOIN
VW_PACK_SPLIT
ON
TBL_CALCULATED_MV.PackCode = VW_PACK_SPLIT.PackCode
AND
TBL_CALCULATED_MV.MarketID = VW_PACK_SPLIT.MarketID
INNER JOIN
TBL_MARKET_PACK MP
ON
TBL_CALCULATED_MV.MarketID = MP.MarketID
AND
TBL_CALCULATED_MV.PackCode = MP.PackCode
WHERE
TBL_CALCULATED_MV.MarketID = #MarketIDs
AND
TBL_CALCULATED_MV.[Month] >= #StartDate
Print 'After sum update'
Print'Before inserting into Initialload table'
/* Changes Done By Rupan (SER00008289)*/
INSERT INTO #tmp_IntialLoad
SELECT DISTINCT
MVQty,
BufferQty,
MP.SplitThreshold,
CONVERT(VARCHAR,Week1Split)+','+CONVERT(VARCHAR,Week2Split)+','+CONVERT(VARCHAR,Week3Split)+','+CONVERT(VARCHAR,Week4Split),
CONVERT(VARCHAR,Week1Split)+','+CONVERT(VARCHAR,Week2Split)+','+CONVERT(VARCHAR,Week3Split)+','+CONVERT(VARCHAR,Week4Split),
MP.PackCode,
TBL_CALCULATED_MV.LocalCustomerCode
FROM
TBL_CALCULATED_MV
LEFT OUTER JOIN VW_PACK_SPLIT
ON TBL_CALCULATED_MV.PackCode = VW_PACK_SPLIT.PackCode
AND TBL_CALCULATED_MV.MarketID = VW_PACK_SPLIT.MarketID
INNER JOIN TBL_MARKET_PACK MP
ON TBL_CALCULATED_MV.MarketID = MP.MarketID
AND TBL_CALCULATED_MV.PackCode = MP.PackCode
WHERE TBL_CALCULATED_MV.MarketID = #MarketIDs
AND TBL_CALCULATED_MV.[Month] >= #StartDate
AND TBL_CALCULATED_MV.Split=1
SET #jSplit = 1
Print 'After Initial load and before looping Initial Load'
WHILE(#jSplit <= (SELECT Count(*) FROM #tmp_IntialLoad ))
BEGIN
SELECT #cQtytoSplit = MVQty,
#cOtherQty = BufferQty,
#cSplitThreshold = SplitThreshold,
#cWeeklySplit = WeeklyMVQty,
#cWeeklyBufferSplit = WeeklyBufferQty,
#cPackCode = PackCode,
#cCustCode = CustomerCode
FROM
#tmp_IntialLoad
WHERE
ID = #jSplit
INSERT INTO #tmp_SplitQTY(SplitType,QtytoSplit,OtherQty,MarketID,Code,CustomerCode,Week1,Week2,Week3,Week4)
EXEC CalculateSplitMV_working_SER8289 #cQtytoSplit,#cOtherQty,#cSplitThreshold,#cWeeklySplit,'MV',#MarketIDs,#cPackCode,NULL
INSERT INTO #tmp_SplitBufferQTY(SplitType,QtytoSplit,OtherQty,MarketID,Code,CustomerCode,Week1,Week2,Week3,Week4)
EXEC CalculateSplitMV_working_SER8289 #cOtherQty,#cQtytoSplit,#cSplitThreshold,#cWeeklyBufferSplit,'BUFFER',#MarketIDs,#cPackCode,NULL
SET #jSplit = #jSplit + 1
END
Print 'After looping Initial Load and before updating #tmp_SplitQTY'
UPDATE ts
SET
ts.Week1Buffer = tsb.Week1,
ts.Week2Buffer = tsb.Week2,
ts.Week3Buffer = tsb.Week3,
ts.Week4Buffer = tsb.Week4
FROM
#tmp_SplitQTY ts,#tmp_SplitBufferQTY tsb
WHERE
ts.ID = tsb.ID
AND
ts.MarketID = tsb.MarketID
AND
ts.Code = tsb.Code
SELECT #tempCount = COUNT(*) FROM #tmp_SplitQTY
Print 'After updating #tmp_SplitQTY and before calling usp_Forecast_Calc_BoxSize sp '
WHILE(#itemp <= #tempCount)
BEGIN
SELECT #tempPackCode = Code,
#tempCustomerCode = CustomerCode,
#tempWeeklyMV = CONVERT(VARCHAR,Week1)+','+CONVERT(VARCHAR,Week2)+','+CONVERT(VARCHAR,Week3)+','+CONVERT(VARCHAR,Week4),
#tempWeeklBuffer = CONVERT(VARCHAR,Week1Buffer)+','+CONVERT(VARCHAR,Week2Buffer)+','+CONVERT(VARCHAR,Week3Buffer)+','+CONVERT(VARCHAR,Week4Buffer),
#tempMVQTY = QtytoSplit,
#tempBufferQTY = OtherQty
FROM
#tmp_SplitQTY
WHERE
ID = #itemp
INSERT INTO #tmp_FinalSplitQTY(MarketID,Code,CustomerCode,Week1,Week2,Week3,Week4,Week1Buffer,Week2Buffer,Week3Buffer,Week4Buffer,QtytoSplit,OtherQty)
EXEC usp_Forecast_Calc_BoxSize #tempWeeklyMV,#tempWeeklBuffer,#MarketIDs,#tempPackCode,NULL,#tempMVQTY,#tempBufferQTY
-- EXEC usp_Forecast_Calc_BoxSize '1,0,0,0','1,1,1,0',5,1120200,NULL,1,3
SET #itemp = #itemp + 1
END
PRINT 'after usp_Forecast_Calc_BoxSize and before Entering MV/Buffer Update'
/* Updating MV Quantity Weekly Split value */
UPDATE tc
SET
tc.Week1MV = tfs.Week1,
tc.Week2MV = tfs.Week2,
tc.Week3MV = tfs.Week3,
tc.Week4MV = tfs.Week4,
tc.Week1Buffer = tfs.Week1Buffer,
tc.Week2Buffer = tfs.Week2Buffer,
tc.Week3Buffer = tfs.Week3Buffer,
tc.Week4Buffer = tfs.Week4Buffer
FROM
TBL_CALCULATED_MV tc,#tmp_FinalSplitQTY tfs
WHERE
tc.PackCode = tfs.code
AND
tc.MarketID = tfs.MarketID
AND
tc.MarketID = #MarketIDs
AND
tc.MVQty = tfs.QtytoSplit
AND
tc.BufferQty = tfs.OtherQty
AND
tc.[Month]>= #StartDate
AND
tc.Split=1
PRINT 'after MV/Buffer Update'
END -- End of Pack Condition
IF #SplitBy = 'Customer' -- Start of Customer condition
BEGIN
Print 'Entering Customer Sum update'
UPDATE TBL_CALCULATED_MV
SET
SumWeeklyMV = MVQty,
SumWeeklyBuffer = BufferQty,
Split = CASE WHEN MP.SplitThreshold IS NULL THEN
0
WHEN MVQty + BufferQty < MP.SplitThreshold THEN
0
ELSE
1
END
FROM TBL_CALCULATED_MV
--LEFT OUTER JOIN VW_CUSTOMER_SPLIT
LEFT OUTER JOIN TBL_CUSTOMER_CODE
ON TBL_CALCULATED_MV.LocalCustomerCode = TBL_CUSTOMER_CODE.CustomerCode
--ON TBL_CALCULATED_MV.LocalCustomerCode = VW_CUSTOMER_SPLIT.CustomerCode
INNER JOIN TBL_MARKET_PACK MP
ON TBL_CALCULATED_MV.MarketID = MP.MarketID
AND TBL_CALCULATED_MV.PackCode = MP.PackCode
WHERE TBL_CALCULATED_MV.MarketID = #MarketIDs
AND TBL_CALCULATED_MV.[Month] >= #StartDate
--* Updating MV Quantity Weekly Split value */
/* Updating MV Quantity Weekly Split value */
Print 'After Customer Sum update'
Print'Before inserting into Initialload table'
INSERT INTO #tmp_IntialLoad
SELECT DISTINCT
MVQty,
BufferQty,
MP.SplitThreshold,
CONVERT(VARCHAR,Week1Split)+','+CONVERT(VARCHAR,Week2Split)+','+CONVERT(VARCHAR,Week3Split)+','+CONVERT(VARCHAR,Week4Split),
CONVERT(VARCHAR,Week1Split)+','+CONVERT(VARCHAR,Week2Split)+','+CONVERT(VARCHAR,Week3Split)+','+CONVERT(VARCHAR,Week4Split),
TBL_CALCULATED_MV.PackCode,
TBL_CALCULATED_MV.LocalCustomerCode
FROM
TBL_CALCULATED_MV
--LEFT OUTER JOIN VW_CUSTOMER_SPLIT
LEFT OUTER JOIN TBL_CUSTOMER_CODE
ON TBL_CALCULATED_MV.LocalCustomerCode = TBL_CUSTOMER_CODE.CustomerCode
--ON TBL_CALCULATED_MV.LocalCustomerCode = VW_CUSTOMER_SPLIT.CustomerCode
INNER JOIN TBL_MARKET_PACK MP
ON TBL_CALCULATED_MV.MarketID = MP.MarketID
AND TBL_CALCULATED_MV.PackCode = MP.PackCode
WHERE TBL_CALCULATED_MV.MarketID = #MarketIDs
AND TBL_CALCULATED_MV.[Month] >= #StartDate
AND TBL_CALCULATED_MV.Split=1
SET #jSplit = 1
Print 'After Initial load and before looping Initial Load'
WHILE(#jSplit <= (SELECT Count(*) FROM #tmp_IntialLoad ))
BEGIN
SELECT #cQtytoSplit = MVQty,
#cOtherQty = BufferQty,
#cSplitThreshold = SplitThreshold,
#cWeeklySplit = WeeklyMVQty,
#cWeeklyBufferSplit = WeeklyBufferQty,
#cPackCode = PackCode,
#cCustCode = CustomerCode
FROM
#tmp_IntialLoad
WHERE
ID = #jSplit
INSERT INTO #tmp_SplitQTY(SplitType,QtytoSplit,OtherQty,MarketID,Code,CustomerCode,Week1,Week2,Week3,Week4)
EXEC CalculateSplitMV_working_SER8289 #cQtytoSplit,#cOtherQty,#cSplitThreshold,#cWeeklySplit,'MV',#MarketIDs,#cPackCode,#cCustCode
INSERT INTO #tmp_SplitBufferQTY(SplitType,QtytoSplit,OtherQty,MarketID,Code,CustomerCode,Week1,Week2,Week3,Week4)
EXEC CalculateSplitMV_working_SER8289 #cOtherQty,#cQtytoSplit,#cSplitThreshold,#cWeeklyBufferSplit,'BUFFER',#MarketIDs,#cPackCode,#cCustCode
SET #jSplit = #jSplit + 1
END
Print 'After looping Initial Load and before updating #tmp_SplitQTY'
UPDATE ts
SET
ts.Week1Buffer = tsb.Week1,
ts.Week2Buffer = tsb.Week2,
ts.Week3Buffer = tsb.Week3,
ts.Week4Buffer = tsb.Week4
FROM
#tmp_SplitQTY ts,#tmp_SplitBufferQTY tsb
WHERE
ts.ID = tsb.ID
AND
ts.MarketID = tsb.MarketID
AND
ts.Code = tsb.Code
AND
ts.CustomerCode = tsb.CustomerCode
SELECT #tempCount = COUNT(*) FROM #tmp_SplitQTY
Print 'After updating #tmp_SplitQTY and before calling usp_Forecast_Calc_BoxSize sp '
WHILE(#itemp <= #tempCount)
BEGIN
SELECT #tempPackCode = Code,
#tempCustomerCode = CustomerCode,
#tempWeeklyMV = CONVERT(VARCHAR,Week1)+','+CONVERT(VARCHAR,Week2)+','+CONVERT(VARCHAR,Week3)+','+CONVERT(VARCHAR,Week4),
#tempWeeklBuffer = CONVERT(VARCHAR,Week1Buffer)+','+CONVERT(VARCHAR,Week2Buffer)+','+CONVERT(VARCHAR,Week3Buffer)+','+CONVERT(VARCHAR,Week4Buffer),
#tempMVQTY = QtytoSplit,
#tempBufferQTY = OtherQty
FROM
#tmp_SplitQTY
WHERE
ID = #itemp
INSERT INTO #tmp_FinalSplitQTY(MarketID,Code,CustomerCode,Week1,Week2,Week3,Week4,Week1Buffer,Week2Buffer,Week3Buffer,Week4Buffer,QtytoSplit,OtherQty)
EXEC usp_Forecast_Calc_BoxSize #tempWeeklyMV,#tempWeeklBuffer,#MarketIDs,#tempPackCode,#tempCustomerCode,#tempMVQTY,#tempBufferQTY
SET #itemp = #itemp + 1
END
PRINT 'after usp_Forecast_Calc_BoxSize and before Entering MV/Buffer Update'
/* Updating MV Quantity Weekly Split value */
UPDATE tc
SET
tc.Week1MV = tfs.Week1,
tc.Week2MV = tfs.Week2,
tc.Week3MV = tfs.Week3,
tc.Week4MV = tfs.Week4,
tc.Week1Buffer = tfs.Week1Buffer,
tc.Week2Buffer = tfs.Week2Buffer,
tc.Week3Buffer = tfs.Week3Buffer,
tc.Week4Buffer = tfs.Week4Buffer
FROM
TBL_CALCULATED_MV tc,#tmp_FinalSplitQTY tfs
WHERE
tc.PackCode = tfs.code
AND
tc.MarketID = tfs.MarketID
AND
tc.LocalCustomerCode = tfs.CustomerCode
AND
tc.MarketID = #MarketIDs
AND
tc.MVQty = tfs.QtytoSplit
AND
tc.BufferQty = tfs.OtherQty
AND
tc.[Month]>= #StartDate
AND
tc.Split=1
/* End */
PRINT 'after MV/Buffer Update'
--check for errors
SELECT #ErrorCode = ##Error
END -- End of Customer condition
END -- End of Errorcode 1
IF #ErrorCode = 0
BEGIN
Print 'Inside sumweekly update'
--Update the SumWeeklyMV and SumWeeklyBuffer fields to be the sum of the
--splits for the rows that are to be split
UPDATE TBL_CALCULATED_MV
SET
TBL_CALCULATED_MV.SumWeeklyMV = ISNULL(Week1MV,0) + ISNULL(Week2MV,0) + ISNULL(Week3MV,0) + ISNULL(Week4MV,0),
TBL_CALCULATED_MV.SumWeeklyBuffer = ISNULL(Week1Buffer,0) + ISNULL(Week2Buffer,0) + ISNULL(Week3Buffer,0) + ISNULL(Week4Buffer,0)
WHERE TBL_CALCULATED_MV.Split=1
and TBL_CALCULATED_MV.MarketID = #MarketIDs
AND TBL_CALCULATED_MV.[Month] >= #StartDate
--check for errors
select #ErrorCode = ##Error
END
IF #ErrorCode = 0
COMMIT TRAN
ELSE
BEGIN
ROLLBACK TRAN
set #Failed = #Failed + ',' + #MarketIDs
END
SET #ErrorCode = 0
/* Start - Rupan
FETCH NEXT FROM MarketCursor
INTO #MarketIDs
End */
DELETE FROM #tmp_IntialLoad
DELETE FROM #tmp_SplitQTY
DELETE FROM #tmp_FinalSplitQTY
SET #iMarketID = #iMarketID + 1
END
/*CLOSE MarketCursor
DEALLOCATE MarketCursor
*/
DROP TABLE #tmp_IntialLoad
DROP TABLE #tmp_SplitQTY
DROP TABLE #tmp_FinalSplitQTY
--IF #Failed is null
--SELECT #SuccessFail = 'All markets were successfully re-calculated'
--ELSE
-- SELECT #SuccessFail=#Failed
END -- END of Procedure Begin
GO
If it has not been done yet, you should:
switch to compatibility lever 120
rebuild indexes
update statistics
clear plan cache and force stored procedures recompile

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