tsql - While Loop issue using temp table - sql-server

Our DBA has changed a function to be a procedure, so I am amending some of my procedures to cater for this. I've come across a problem with this in one of my procedures where I have a while loop.
I populate my temp table from the new procedure (#DGContol), and then have the following while loop:
SELECT #MinRcd = MIN(RcdNum) FROM #PortfolioDisclosure
SELECT #MaxRcd = MAX(RcdNum) FROM #PortfolioDisclosure
SET #RcdNum = #MinRcd
WHILE #RcdNum <= #MaxRcd
BEGIN
-- Temporarily assign values to variables
SELECT
#PortfolioGroup = PortfolioCode
, #EndDateTime = MaxPositionDate_DetailedDisclosure
FROM #PortfolioDisclosure
WHERE RcdNum = #RcdNum
INSERT INTO #PositionsTable
SELECT
fi.ID_ISIN AS [Fund_ISIN]
, RTRIM(a.acct_id) AS [Internal_Portfolio_Code]
, a.acct_desc AS [Portfolio/Fund_Name]
, CONVERT(CHAR(11),p.as_of_tms,103) AS [Portfolio_Date]
, a.alt_curr_cde AS [Portfolio_Base_Ccy]
, i.iss_desc AS [Security_Description]
, RTRIM(i.pref_iss_id) AS [Security_ID SEDOL/Internal]
, RTRIM(ia.iss_id) AS [Security_ID ISIN]
, i.denom_curr_cde AS [Denomination_Ccy]
, SUM(p.valval_alt_cmb_amt) OVER (PARTITION BY RTRIM(a.acct_id))
AS [Total_Fund_Value]
, p.orig_quantity AS [Shares/Par_Value]
, p.valval_alt_cmb_amt AS [Market_Value]
, p.fld5_rte AS [Pct_of_NAV]
, SUM(CASE WHEN i.issue_cls1_cde = '010' THEN p.valval_alt_cmb_amt ELSE 0 END) OVER (PARTITION BY a.acct_id)
AS [Cash/Cash_Equivalents]
, i.inc_proj_cmb_rte AS [Coupon_Rate]
, CONVERT(CHAR(11),i.mat_exp_dte,103) AS [Maturity_Date]
FROM dw_position_dg AS p
INNER JOIN #DGControl AS dgc -- [M]onthly, [M]ost recent position
ON dgc.DataGrpCtlNum = p.data_grp_ctl_num
INNER JOIN dw_ivw_acct AS a WITH (NOLOCK)
ON a.acct_id = p.acct_id
INNER JOIN dw_issue_dg AS i WITH (NOLOCK)
ON i.instr_id = p.instr_id
LEFT OUTER JOIN dw_issue_alt_id AS ia WITH (NOLOCK)
ON ia.instr_id = i.instr_id
AND ia.id_ctxt_typ = 'ISIN'
INNER JOIN #PortfolioDisclosure AS fi
ON fi.PortfolioCode = p.acct_id
and fi.MaxPositionDate_DetailedDisclosure >= p.as_of_tms
WHERE RTRIM(a.acct_id) NOT IN ( SELECT xref.internal_value FROM dbo.DP_CrossReference as xref
WHERE xref.Codeset_type_id = 10401
AND xref.Originator_id = 'DataVendorPortfolioExclusion')
-- Clear down variable values
SET #PortfolioGroup = NULL
--SET #StartDateTime = NULL
SET #EndDateTime = NULL
-- Move to next record
SET #RcdNum = #RcdNum + 1
END -- END WHILE LOOP
However this returns lots of duplicate records. If I replace the temp table #DGControl with the original function then I get the correct number of records.
I don't really know what the issue would be or how I could re code this while loop so that using the table #DGControl I get the correct number of records. Can anyone help?

Have you compared the output of SELECT * FROM OldFunction(args..) with EXEC NewStoredProcedure args...? If so, does the data returned look the same or has the duplication crept in when the DBA refactored the function to a proc.
If so you may need to de dupe the output from the sp first then run it through your remaining code. In short, if you are using the same arguments for both but they give you different results then you'll need to go back to the DBA.

You aren't using either of your local variables (#PortfolioGroup, #EndDateTime) in this code. It is just inserting the same record set N number of times. Also, I think you can write this as a single select query without using temp tables or while loops and it will make it less confusing.

Thank you for your feedback. i worked out the issue. My code looks like the following now:
BEGIN
SELECT #MinRcd = MIN(RcdNum) FROM #PortfolioDisclosure
SELECT #MaxRcd = MAX(RcdNum) FROM #PortfolioDisclosure
SET #RcdNum = #MinRcd
WHILE #RcdNum <= #MaxRcd
BEGIN
-- Temporarily assign values to variables
SELECT
#PortfolioGroup = PortfolioCode
, #EndDateTime = MaxPositionDate_DetailedDisclosure
FROM #PortfolioDisclosure
WHERE RcdNum = #RcdNum
-- Insert DGControl record into table based on the MaxPositionDate_DetailedDisclosure from Portfolio Disclosure function
INSERT INTO #DGControl
EXEC InfoPortal..usp_Generic_DGControl '', '', #PortfolioGroup, '1', #EndDateTime, #EndDateTime, #PeriodType, 'M', 'POSITION' -- [M]onthly, [M]ost recent position
-- Insert into #PositionsTable
INSERT INTO #PositionsTable
SELECT
fi.ID_ISIN AS [Fund_ISIN]
, RTRIM(a.acct_id) AS [Internal_Portfolio_Code]
, a.acct_desc AS [Portfolio/Fund_Name]
, CONVERT(CHAR(11),p.as_of_tms,103) AS [Portfolio_Date]
, a.alt_curr_cde AS [Portfolio_Base_Ccy]
, i.iss_desc AS [Security_Description]
, RTRIM(i.pref_iss_id) AS [Security_ID SEDOL/Internal]
, RTRIM(ia.iss_id) AS [Security_ID ISIN]
, i.denom_curr_cde AS [Denomination_Ccy]
, SUM(p.valval_alt_cmb_amt) OVER (PARTITION BY RTRIM(a.acct_id))
AS [Total_Fund_Value]
, p.orig_quantity AS [Shares/Par_Value]
, p.valval_alt_cmb_amt AS [Market_Value]
, p.fld5_rte AS [Pct_of_NAV]
, SUM(CASE WHEN i.issue_cls1_cde = '010' THEN p.valval_alt_cmb_amt ELSE 0 END) OVER (PARTITION BY a.acct_id)
AS [Cash/Cash_Equivalents]
, i.inc_proj_cmb_rte AS [Coupon_Rate]
, CONVERT(CHAR(11),i.mat_exp_dte,103) AS [Maturity_Date]
FROM dw_position_dg AS p
INNER JOIN #DGControl AS dgc
ON dgc.DataGrpCtlNum = p.data_grp_ctl_num
INNER JOIN dw_ivw_acct AS a WITH (NOLOCK)
ON a.acct_id = p.acct_id
INNER JOIN dw_issue_dg AS i WITH (NOLOCK)
ON i.instr_id = p.instr_id
LEFT OUTER JOIN dw_issue_alt_id AS ia WITH (NOLOCK)
ON ia.instr_id = i.instr_id
AND ia.id_ctxt_typ = 'ISIN'
INNER JOIN #PortfolioDisclosure AS fi
ON fi.PortfolioCode = p.acct_id
-- Clear down variable values
SET #PortfolioGroup = NULL
--SET #StartDateTime = NULL
SET #EndDateTime = NULL
-- Clear down #DGControl table to allow new record to be inserted
DELETE FROM #DGControl
-- Move to next record
SET #RcdNum = #RcdNum + 1
END -- END WHILE LOOP
Adding the execution of the stored proc usp_Generic_DGControl at the beginning and then clearing it down after each loop stopped the duplication of the records.

Related

TSQL Dynamic Update of TOP(n) Rows

i have a table with one line per travel
second table has values of origin and destination and quantity for each combination
i need to run an update that run on the second table that update top N rows on the first table (n comes from the second table)
im using this update script inside a cursor in a procedure :
ALTER PROCEDURE [dbo].[SP_Travels_History_FromMissing]
AS
BEGIN
SET NOCOUNT ON;
DECLARE #C_Day_Type_Code INT = NULL
DECLARE #C_PartOfDay_Code INT = NULL
DECLARE #C_Station_From INT = NULL
DECLARE #C_DestinationStation INT = NULL
DECLARE #C_Deploy INT = NULL
TRUNCATE TABLE [TCK_TMP_Fact_ALL_Travels_History_FromMissing]
INSERT
INTO [TCK_TMP_Fact_ALL_Travels_History_FromMissing]
SELECT TRV.Day_Type_Code,
TRV.PartOfDay_Code,
HIS.Station_From,
TRV.DestinationStation,
-- TRV.TotalTravels,
-- HIS.Percentage,
-- (TRV.TotalTravels * HIS.Percentage) / 100,
CAST(CEILING((TRV.TotalTravels * HIS.Percentage) / 100) AS INT) Deploy
FROM
(
SELECT DAT.Day_Type_Code,
-- DATEPART(HOUR,[EntranceDate]) EntranceHour,
POD.PartOfDay_Code,
DestinationStation,
COUNT(*) TotalTravels
FROM [Tickets].[dbo].[TCK_STG_Fact_Contract_Magnetic_Travels1] TRV
LEFT OUTER JOIN [Tickets].[dbo].[TCK_DWH_Dim_Date] DAT ON CAST(TRV.[ExitDate] AS DATE) = CAST(DAT.Date AS DATE)
LEFT OUTER JOIN [Tickets].[dbo].[TCK_DWH_Dim_Manual_PartOfDay] POD ON DATEPART(HOUR,TRV.[ExitDate]) = POD.PartOfDay_Hour
WHERE [EventID_Entrance] = -1
GROUP BY DAT.Day_Type_Code,
POD.PartOfDay_Code,
DestinationStation
) TRV
LEFT OUTER JOIN
(
SELECT *
FROM [dbo].[TCK_DWH_Fact_ALL_Travels_History_FromMissing]
WHERE [Total_Travels] IS NOT NULL
) HIS ON HIS.Day_Type_Code = TRV.Day_Type_Code
AND HIS.PartOfDay_Code = TRV.PartOfDay_Code
AND HIS.Station_To = TRV.DestinationStation
WHERE CAST(CEILING((TRV.TotalTravels * HIS.Percentage) / 100) AS INT) > 0
ORDER BY 1,2,4,5 DESC
DECLARE Missing_Cursor CURSOR FOR
SELECT [Day_Type_Code],
[PartOfDay_Code],
DestinationStation,
Station_From,
[Deploy]
FROM [Tickets].[dbo].[TCK_TMP_Fact_ALL_Travels_History_FromMissing]
ORDER BY [Day_Type_Code],
[PartOfDay_Code],
DestinationStation,
[Deploy] DESC,
Station_From
OPEN Missing_Cursor
FETCH NEXT
FROM Missing_Cursor
INTO #C_Day_Type_Code,
#C_PartOfDay_Code,
#C_DestinationStation,
#C_Station_From,
#C_Deploy
WHILE ##FETCH_STATUS = 0
BEGIN
UPDATE TOP (#C_Deploy) TRV
SET TRV.SourceStationID = #C_Station_From,
TRV.MissingStationSourceCode = 888
FROM [Tickets].[dbo].TCK_STG_Fact_Contract_Magnetic_Travels1 TRV
LEFT OUTER JOIN [Tickets].[dbo].[TCK_DWH_Dim_Date] DAT ON CAST(TRV.[ExitDate] AS DATE) = CAST(DAT.Date AS DATE)
LEFT OUTER JOIN [Tickets].[dbo].[TCK_DWH_Dim_Manual_PartOfDay] POD ON DATEPART(HOUR,TRV.[ExitDate]) = POD.PartOfDay_Hour
WHERE DAT.Day_Type_Code = #C_Day_Type_Code
AND POD.PartOfDay_Code = #C_PartOfDay_Code
AND TRV.DestinationStation = #C_DestinationStation
AND TRV.SourceStationID IS NULL
-- COMMIT;
-- ORDER BY TRV.ContractID
-- LIMIT #C_Deploy;
-------------------------
FETCH NEXT
FROM Missing_Cursor
INTO #C_Day_Type_Code,
#C_PartOfDay_Code,
#C_DestinationStation,
#C_Station_From,
#C_Deploy
END
CLOSE Missing_Cursor
DEALLOCATE Missing_Cursor
END
Problem is It Takes more then 30 minutes
how can i use a dynamic update without a cursor?
any other suggestions are welcome

SQL Server trigger after insert to another database is not firing

Previously I had a TRIGGER in Table46 to fire after an insert to send a message to another server using Service Broker, which was working fine:
CREATE TRIGGER trgSendItemData
ON [dbo].[Table46]
AFTER INSERT
AS
DECLARE #new_event XML;
SET #new_event = (
SELECT i.[046_ID] AS [id]
, NP.NoPart + ' ' + CONVERT(VARCHAR(3), T41.[041_No]) AS [name]
, DATEADD(MINUTE, -1 * i.[046_ExeTime], i.[046_DateTime]) AS [eventstart]
, i.[046_DateTime] AS [eventend]
, i.[046_IDRes] AS [resource_id]
, i.[046_ExeTime] AS [execution]
, ISNULL(MIN(T48.[048_MachTime]), 0) AS [same]
, ISNULL(MIN(T48_1.[048_MachTime]), 0) AS [all]
, i.[046_Pallet] AS [pallet]
FROM inserted AS i
INNER JOIN Table41 AS T41
ON i.[046_IDOp] = T41.[041_IDOp]
INNER JOIN NoParts AS NP
ON T41.[041_IDNoPart] = NP.Autonumber
INNER JOIN Table48 AS T48
ON i.[046_IDRes] = T48.[048_IDRes]
AND i.[046_IDOp] = T48.[048_IDOp]
INNER JOIN Table48 AS T48_1
ON i.[046_IDOp] = T48_1.[048_IDOp]
GROUP BY i.[046_ID], NP.NoPart, T41.[041_No], i.[046_MachTime],
i.[046_DateTime], i.[046_IDRes], i.[046_ExeTime], i.[046_Pallet];
FOR XML AUTO, ELEMENTS
);
DECLARE #ConvHandle UNIQUEIDENTIFIER;
BEGIN TRANSACTION
BEGIN DIALOG #ConvHandle
FROM SERVICE SenderService
TO SERVICE 'ReceiverService'
ON CONTRACT STContract
WITH ENCRYPTION = OFF;
SEND ON CONVERSATION #ConvHandle
MESSAGE TYPE SenderMsg (#new_event);
COMMIT TRANSACTION;
GO
Now I need that same data in a table of another database but in the same server, so I wrote this one which is not working:
USE Database1
GO
CREATE TRIGGER trgSendEvent
ON [dbo].[Table46]
AFTER INSERT
AS BEGIN
SET NOCOUNT ON;
INSERT INTO [Database2].[dbo].[Events]
([id]
,[name]
,[eventstart]
,[eventend]
,[resource_id]
,[execution]
,[same]
,[all]
,[pallet])
SELECT i.[046_ID] AS [id]
, NP.NoPart + ' ' + CONVERT(VARCHAR(3), T41.[041_No]) AS [name]
, DATEADD(MINUTE, -1 * i.[046_ExeTime], i.[046_DateTime]) AS [eventstart]
, i.[046_DateTime] AS [eventend]
, i.[046_IDRes] AS [resource_id]
, i.[046_ExeTime] AS [execution]
, ISNULL(MIN(T48.[048_MachTime]), 0) AS [same]
, ISNULL(MIN(T48_1.[048_MachTime]), 0) AS [all]
, i.[046_Pallet] AS [pallet]
FROM inserted AS i
INNER JOIN Table41 AS T41
ON i.[046_IDOp] = T41.[041_IDOp]
INNER JOIN NoParts AS NP
ON T41.[041_IDNoPart] = NP.Autonumber
INNER JOIN Table48 AS T48
ON i.[046_IDRes] = T48.[048_IDRes]
AND i.[046_IDOp] = T48.[048_IDOp]
INNER JOIN Table48 AS T48_1
ON i.[046_IDOp] = T48_1.[048_IDOp]
GROUP BY i.[046_ID], NP.NoPart, T41.[041_No], i.[046_MachTime],
i.[046_DateTime], i.[046_IDRes], i.[046_ExeTime], i.[046_Pallet];
END;
GO
I know that it isn't working because if I manually run a query to insert a new row in Table46, the new row is added in Table46, but not in Database2.Events. This is what I get as output:
(1 row affected)
Should I get that twice instead?
Also, Table46 constantly receives data but when the trigger is created it stops receiving it.
I also tried running a query to enable the trigger in case it's disabled, but nothing changes.

Update row with values from select on condition, else insert new row

I'm need to run a calculation for month every day. If the month period, exists already, I need to update it, else I need to create a new row for the new month.
Currently, I've written
declare #period varchar(4) = '0218'
DECLARE #Timestamp date = GetDate()
IF EXISTS(select * from #output where period=#period)
/* UPDATE #output SET --- same calculation as below ---*/
ELSE
SELECT
#period AS period,
SUM(timecard.tworkdol) AS dol_local,
SUM(timecard.tworkdol/currates.cdrate) AS dol_USD,
SUM(timecard.tworkhrs) AS hrs,
#Timestamp AS timestamp
FROM dbo.timecard AS timecard
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
SELECT * FROM #output;
How can simply update my row with the new data from my select.
Not sure what RDBMS are you using, but in SQL Server something like this would update the #output table with the results of the SELECT that you placed in the ELSE part:
UPDATE o
SET o.dol_local = SUM(timecard.tworkdol),
SET o.dol_USD = SUM(timecard.tworkdol/currates.cdrate),
SET o.hrs = SUM(timecard.tworkhrs),
set o.timestamp = #Timestamp
FROM #output o
INNER JOIN dbo.timecard AS timecard ON o.period = timecard.twoper
INNER JOIN dbo.timekeep ON timecard.ttk = timekeep.tkinit
INNER JOIN dbo.matter with (nolock) on timecard.tmatter = matter.mmatter
LEFT JOIN dbo.currates with (nolock) on matter.mcurrency = currates.curcode
AND currates.trtype = 'A'
AND timecard.tworkdt BETWEEN currates.cddate1
AND currates.cddate2
WHERE timekeep.tkloc IN('06','07') AND
timecard.twoper = #period
Also, I think you want to do an INSERT in the ELSE part, but you are doing just a SELECT, so I guess you should fix that too
The answer to this will vary by SQL dialect, but the two main approaches are:
1. Upsert (if your DBMS supports it), for example using a MERGE statement in SQL Server.
2. Base your SQL on an IF:
IF NOT EXISTS (criteria for dupes)
INSERT INTO (logic to insert)
ELSE
UPDATE (logic to update)

Error creating stored procedure in SQL Server with PIVOT operator

I am getting this error when I attempt to create a stored procedure:
SQL Server Database Error: Incorrect syntax near the keyword 'PROC'.
When I execute the SQL between the lines, everything works. However, when I attempt to execute the stored procedure, I get the error.
I'm new to stored procedures, so I am hoping that it is just a misplaced ; or GO.
SET ANSI_NULLS ON;
GO
SET QUOTED_IDENTIFIER ON;
GO
IF EXISTS (SELECT object_id FROM AppGovernmentPrograms.Sys.Objects
WHERE type = 'P'
AND name = 'usp_AppGovernmentPrograms_rptObjectives')
BEGIN
DROP PROCEDURE dbo.usp_AppGovernmentPrograms_rptObjectives
END
GO
CREATE PROC [dbo].[usp_AppGovernmentPrograms_rptObjectives]
#ProgramYear INT,
#SummaryLevel VARCHAR(50)
AS
SET NOCOUNT ON;
WITH measuresPHS AS
(
SELECT
mi.definition_id, mi.metric_name
FROM
StgEpicClarityPHS.dbo.metric_info mi WITH (nolock)
WHERE
mi.definition_id IN (90020350, 90020300, 90020301, 90020302,
90020303, 90020304, 90020305, 90020306,
90020307, 90020308, 90020309, 90020310,
90020311, 90020351, 90020352, 90020353,
90020354, 90020355, 90020400)
)
SELECT
provCID, NPI, TIN, year_dt,
SUM([n90020350]) as "1.1n",
SUM([d90020350]) as "1.1d",
SUM([n90020300]) as "2.1n",
SUM([d90020300]) as "2.1d",
SUM([n90020301]) as "4.1n",
SUM([d90020301]) as "4.1d",
SUM([n90020302]) as "4.2n",
SUM([d90020302]) as "4.2d",
SUM([n90020303]) as "4.3n",
SUM([d90020303]) as "4.3d",
SUM([n90020304]) as "5.1n",
SUM([d90020304]) as "5.1d",
SUM([n90020305]) as "5.2n",
SUM([d90020305]) as "5.2d",
SUM([n90020306]) as "6.1n",
sum([d90020306]) as "6.1d"
, sum([n90020307]) as "6.2n"
, sum([d90020307]) as "6.2d"
, sum([n90020308]) as "6.3n"
, sum([d90020308]) as "6.3d"
, sum([n90020309]) as "7.1n"
, sum([d90020309]) as "7.1d"
, sum([n90020310]) as "7.2n"
, sum([d90020310]) as "7.2d"
, sum([n90020311]) as "7.3n"
, sum([d90020311]) as "7.3d"
, sum([n90020351]) as "8.1n"
, sum([d90020351]) as "8.1d"
, sum([n90020352]) as "8.2n"
, sum([d90020352]) as "8.2d"
, sum([n90020353]) as "8.3n"
, sum([d90020353]) as "8.3d"
, sum([n90020354]) as "8.4n"
, sum([d90020354]) as "8.4d"
, sum([n90020355]) as "8.5n"
, sum([d90020355]) as "8.5d"
, sum([n90020400]) as "IAn"
, sum([d90020400]) as "IAd"
From
(
Select
sfi.prov_target_id as provCID
, prov2.npi
, cmi.facility_group_id as TIN
, sum_data.year_dt
, 'n' + cast(sfi.definition_id as varchar(15)) as id1 -- use for numerator
, 'd' + cast(sfi.definition_id as varchar(15)) as id2 -- use for denominator
, sum_data.numerator_year
, sum_data.denominator_year
from StgEpicClarityPHS.dbo.sum_facts_info sfi with(nolock)
inner join StgEpicClarityPHS.dbo.sum_facts_info_2 sfi2 with(nolock) on sfi2.sum_facts_id = sfi.sum_facts_id
inner join measuresPHS m with(nolock) on m.definition_id = sfi.definition_id
inner join StgEpicClarityPHS.dbo.yearly_data sum_data with(nolock) on sum_data.sum_facts_id = sfi.sum_facts_id
left outer join StgEpicClarityPHS.dbo.cms_mu_info cmi with(nolock) on cmi.cms_mu_id = sfi2.tin_target_id
left outer join StgEpicClarityPHS.dbo.clarity_ser_2 prov2 with(nolock) on sfi.prov_target_id = prov2.prov_id
Where sfi.record_type_c = 1 -- standard summary, not a benchmark
and (sum_data.year_dt = cast(concat('01/01/',:ProgramYear) as datetime)) -- (always use the start date of the reporting period)
and (
(:SummaryLevel = 'NT' and sfi.compld_sum_level = '4^73') -- NPI/TIN (i.e. individual MIPS EC)
or
(:SummaryLevel = 'T' and sfi.compld_sum_level = '73') -- TIN (i.e. Group)
or
(:SummaryLevel = 'N' and sfi.compld_sum_level = '4') -- NPI only
)
) nd
pivot
( sum(NUMERATOR_YEAR)
for id1 in ([n90020350], [n90020300], [n90020301], [n90020302], [n90020303], [n90020304], [n90020305], [n90020306], [n90020307], [n90020308], [n90020309], [n90020310], [n90020311], [n90020351], [n90020352], [n90020353], [n90020354], [n90020355], [n90020400])
) as p1
pivot
( sum(DENOMINATOR_YEAR)
for id2 in ([d90020350], [d90020300], [d90020301], [d90020302], [d90020303], [d90020304], [d90020305], [d90020306], [d90020307], [d90020308], [d90020309], [d90020310], [d90020311], [d90020351], [d90020352], [d90020353], [d90020354], [d90020355], [d90020400])
) as p2
Group By provCID, NPI, TIN, year_dt
--------------------------------------------------------------------------------------------------------------------------------------
;
GO
Your problem may simply be that your query contains a colon at
cast(concat('01/01/',:ProgramYear) as datetime)
in your where clause. It should probably be a #ProgramYear
Also :SummaryLevel should be #SummaryLevel

Old SQL Query Optimization

I have a pre written SQL Query, which takes 45 minutes to actually run and show the data. It returns total 80000+ records. But it takes hell lot of time to run and show the data.
SELECT
hq.QuoteHeaderId,
hq.HandsetQuoteId,
hq.QuoteDate,
t_PhoneAudit.PhoneModelId,
t_PhoneAudit.IMEI,
t_PhoneModel.ModelName,
t_PhoneBrand.Name As BrandName
, al.ActivityId
, par.Result
, al.CustomMessage,
al.[Description]
,thqai.Value AS AgentName
FROM [t_DynaGroupMissingRecordsProcessing]
INNER JOIN t_HandsetQuote hq ON t_DynaGroupMissingRecordsProcessing.HandsetQuoteId = hq.HandsetQuoteId
INNER JOIN t_PhoneAudit ON t_PhoneAudit.PhoneAuditId = hq.QuotePhoneAuditId
INNER JOIN t_PhoneModel ON t_PhoneModel.PhoneModelId = t_PhoneAudit.PhoneModelId
INNER JOIN t_PhoneBrand ON t_PhoneBrand.PhoneBrandId = t_PhoneModel.PhoneBrandId
INNER JOIN
(
SELECT par.HandsetQuoteId, txt_Value AS ActivityId, 'OK' AS Result FROM t_PhoneAuditRetail par CROSS APPLY dbo.fn_ParseText2Table(par.Ok, ',')
UNION
SELECT par.HandsetQuoteId, txt_Value AS ActivityId, 'Fault' AS Result FROM t_PhoneAuditRetail par CROSS APPLY dbo.fn_ParseText2Table(par.Fault, ',')
) par ON hq.HandsetQuoteId = par.HandsetQuoteId
INNER JOIN t_ActivityLocalization al ON par.ActivityId = al.ActivityId
INNER JOIN t_ContactChannel CC ON al.ContactChannelId = CC.ContactChannelId
INNER JOIN t_testingProfiledetails ON t_testingProfiledetails.ActivityId = al.ActivityId AND ( IsVisibleForRetail = '1' OR t_testingProfiledetails.ActivityId IN ('93','97')) AND t_testingProfiledetails.ProfileId IN (SELECT DefailtRetailProfileId FROM t_ContactChannel WHERE Name IN ('Holland Retail', 'BelCompanyNPEY Retail', 'Belcompany Retail', 'HollandNPEY Retail'))
LEFT OUTER JOIN t_HandsetQuoteAdditionalInfo thqai on thqai.HandsetQuoteId = hq.HandsetQuoteId and thqai.KeyName = 'AgentName'
WHERE [t_DynaGroupMissingRecordsProcessing].IsProcessed = 0
AND CC.Name IN ('Holland Retail', 'BelCompanyNPEY Retail', 'Belcompany Retail', 'HollandNPEY Retail')
ORDER BY hq.HandsetQuoteId
The main problem is with CC.Name IN ('Holland Retail', 'BelCompanyNPEY Retail', 'Belcompany Retail', 'HollandNPEY Retail') this statement.
If i keep on adding the name in the In Statement, the query becomes more and more slow.
Below is the defintion for the function i am using:
ALTER FUNCTION [dbo].[fn_ParseText2Table]
(
#p_SourceText VARCHAR(8000)
,#p_Delimeter VARCHAR(100) = ',' --default to comma delimited.
)
RETURNS #retTable TABLE
(
txt_value VARCHAR(2000)
)
AS
BEGIN
DECLARE #w_Continue int
,#w_StartPos int
,#w_Length int
,#w_Delimeter_pos int
,#w_tmp_txt VARCHAR(2000)
,#w_Delimeter_Len tinyint
SET #w_Continue = 1
SET #w_StartPos = 1
SET #p_SourceText = RTRIM( LTRIM( #p_SourceText))
SET #w_Length = DATALENGTH( RTRIM( LTRIM( #p_SourceText)))
SET #w_Delimeter_Len = len(#p_Delimeter)
WHILE #w_Continue = 1
BEGIN
SET #w_Delimeter_pos = CHARINDEX(#p_Delimeter,(SUBSTRING( #p_SourceText, #w_StartPos,((#w_Length - #w_StartPos)+#w_Delimeter_Len))))
IF #w_Delimeter_pos > 0 -- delimeter(s) found, get the value
BEGIN
SET #w_tmp_txt = LTRIM(RTRIM( SUBSTRING( #p_SourceText, #w_StartPos
,(#w_Delimeter_pos - 1)) ))
SET #w_StartPos = #w_Delimeter_pos + #w_StartPos + (#w_Delimeter_Len- 1)
END
ELSE -- No more delimeters, get last value
BEGIN
SET #w_tmp_txt = LTRIM(RTRIM( SUBSTRING( #p_SourceText, #w_StartPos
,((#w_Length - #w_StartPos) + #w_Delimeter_Len)) ))
SELECT #w_Continue = 0
END
INSERT INTO #retTable VALUES( #w_tmp_txt )
END
RETURN
END
Please help me to optimize this query.
you can try this
Insert the list of names to #table(name) and join it to cc
on cc.name=#table.name

Resources