How to optimise a stored procedure that is too slow? [closed] - sql-server

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 5 years ago.
Improve this question
My stored procedure is taking around 1 minute 45 seconds, how can I optimize it? I tried couple of things like creating temp table before doing the insert.
I have Estimated Execution Plan but I don't know how to upload it.
This is part of my stored procedure which is taking longer time and Query Cost is 53%.
SELECT Distinct
BackupCTE.[InstanceName]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.EnvironmentType = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.EnvironmentType) END AS EnvironmentType
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.InstanceStatus = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.InstanceStatus) END AS [InstanceStatus]
,BackupCTE.[BackupShare]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DatabaseOwner = 0 THEN '-1'
WHEN ISNULL(BackupCTE.IsMirroringEnabled,0) = 0 AND BackupCTE.DatabaseOwner NOT IN ('SA') AND BackupCTE.DatabaseStatus = 'Normal' AND BackupCTE.DatabaseReadOnly = 0
AND ISNULL(BackupCTE.IsDatabaseSnapshot,0) = 0 THEN '0'
ELSE '1' END AS DatabaseOwner
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DBRecoveryModel = 0 THEN '-1'
WHEN BackupCTE.DatabaseStatus = 'Normal' AND BackupCTE.DatabaseName NOT IN ('master', 'msdb', 'IHC_DBA','distribution','ReportServerTempDB','NavicareReporting','ReportServer') AND
BackupCTE.RecoveryModel NOT IN ('Full','BulkLogged') THEN '0'
ELSE '1'
END AS [DBRecoveryModel]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.AutoShrink = 0 THEN '-1'
ELSE CONVERT(VARCHAR, BackupCTE.[AutoShrink]) END AS [AutoShrink]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.AutoClose = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.[AutoClose]) END AS [AutoClose]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.BackupCompression = 0 THEN '-1'
WHEN BackupCTE.[BackupCompression] = 0 THEN '0'
Else '1' END AS [BackupCompression]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.XPCmdShell = 0 THEN '-1'
WHEN CONVERT(VARCHAR,BackupCTE.[XPCmdShell]) = 0 THEN '1'
Else '0' END AS [XPCmdShell]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.EncryptionEnabled = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.[EncryptionEnabled]) END AS [EncryptionEnabled]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.IsIdera = 0 THEN '-1' Else CONVERT(VARCHAR,BackupCTE.[IsIdera]) END AS [IsIdera]
,[HoursRetentionShare]
,[HoursSinceLastFullBackup]
,[HoursSinceLastDiffBackup]
,[HoursSinceLastLogBackup]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.ExceededBkpTimeFrame = 0 THEN '-1' Else BackupCTE.ExceededBkpTimeFrame
END AS ExceededBkpTimeFrame
,BackupType
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[Primary] = 0 THEN '-1' Else BackupCTE.[Primary] END AS [Primary]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[Secondary] = 0 THEN '-1' Else BackupCTE.[Secondary] END AS [Secondary]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[LockPages] = 0 THEN '-1'
Else CONVERT(varchar,BackupCTE.[LockPages]) END AS [LockPages]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[SADisabled] = 0 THEN '-1'
WHEN CONVERT(varchar,BackupCTE.[SADisabled]) = 0 AND BackupCTE.VersionName like 'Microsoft SQL Server 2000 %' THEN '1'
ELSE CONVERT(varchar,BackupCTE.[SADisabled])
END AS [SADisabled]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.ServiceAccount = 0 THEN '-1'
WHEN StdServiceAccount.IsValid = 1
OR BackupCTE.ServiceAccount IN ('CO\lpsqldbadmin','lpsqldbadmin#CO.IHC.COM')
THEN '1'
ELSE '0' END AS ServiceAccount
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[ServicePackFlag] = 0 THEN '-1' Else BackupCTE.[ServicePack] END AS [ServicePack]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[MaxMemory] = 0 THEN '-1' Else BackupCTE.[MaxMemory] END AS [MaxMemory]
,[JobName]
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[JobOwner] = 0 THEN '-1'
WHEN BackupCTE.JobOwner NOT IN ('SA') AND JobEnabled = 1 AND DELETED IS NULL THEN '0'
ELSE '1' END AS JobOwner
,[JobEnabled]
,CASE WHEN BackupCTE.EnvironmentType = 'PROD' AND BackupCTE.[Primary] NOT IN ('Tamie Jensen', 'Chase Mahony','Megna Musapeta','Aaron Uppencamp') THEN '0'
WHEN BackupCTE.EnvironmentType = 'STBY' AND BackupCTE.[Primary] NOT IN ('Tamie Jensen', 'Chase Mahony','Megna Musapeta','Aaron Uppencamp') THEN '0'
ELSE '1' END AS IsNonPrimary
,CASE WHEN BackupCTE.EnvironmentType = 'PROD' AND BackupCTE.[Secondary] IN ('NONE') THEN '0'
WHEN BackupCTE.EnvironmentType = 'STBY' AND BackupCTE.[Secondary] IN ('NONE') THEN '0'
ELSE '1' END AS IsNonSecondary
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.[MaxMemory] = 0 THEN '-1'
WHEN BackupCTE.[MaxMemory]%8 = 0 THEN '1'
ELSE '0' END AS FlagMemory
,CASE WHEN BackupCTE.JobName NOT LIKE '%Insure%'
THEN
CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.MaintenanceJob = 0 THEN '-1'
WHEN JobSchMultiplier < 0 THEN '1' --One Time Job. No Need To Flag
WHEN DATEDIFF(HH, BackupCTE.JobRunDate, GETDATE()) > 24*JobSchMultiplier THEN '0'
ELSE '1'
END
ELSE '1' END AS MaintenanceJob
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.ServicePackFlag = 0 THEN '-1'
WHEN LTRIM(RTRIM(SUBSTRING(PatchingStds.ServicePack,3, LEN(PatchingStds.ServicePack)-2))) > ISNULL(LTRIM(RTRIM(SUBSTRING(InstanceSQLDTl.ServicePack,3,
LEN(InstanceSQLDTl.ServicePack)-2))),0) THEN '0'
WHEN LTRIM(RTRIM(SUBSTRING(VersionName,CHARINDEX('-',VersionName )+1,abs(CASE WHEN CHARINDEX('(',VersionName ) > 0 THEN CHARINDEX('(',VersionName )-CHARINDEX('-',VersionName) ELSE len(VersionName)-CHARINDEX('-',VersionName) end)))) <> LTRIM(RTRIM(PatchingStds.SQLBuild)) THEN '2'
ELSE '1' END AS ServicePackFlag
,VersionName
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.SAViolations = 0 THEN '-1'
WHEN LoginName Not IN ('CO\DBA Group','CO\DBAdmin') AND SYSAdmin = 1 OR SecurityAdmin = 1 OR ServerAdmin = 1 OR SetupAdmin = 1 OR ProcessAdmin = 1 OR DiskAdmin = 1
OR DBCreator = 1 OR BulkAdmin = 1 THEN '0'
ELSE '1' END AS SAViolations
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.IsBackupShare = 0 THEN '-1'
WHEN NOT (BackupCTE.[BackupShare] LIKE '\\CO.IHC.COM%' OR BackupCTE.[BackupShare] LIKE '\\CO-LP-SQL1%' OR BackupCTE.[BackupShare] LIKE '\\CO-LP-SQL2%'
OR BackupCTE.[BackupShare] LIKE '\\CO-TX-VAULT2%' OR BackupCTE.[BackupShare] LIKE '\\co-tx-vpdsfile2\txPDSsqlBackups%' AND BackupCTE.[BackupShare] NOT LIKE '%Test') OR BackupCTE.[BackupShare] = 'NONE LISTED' THEN '0'
ELSE '1' END AS IsBackupShare
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.Tempdb_DataFileCount = 0 THEN '-1'
WHEN TEMPDBFileCount.Tempdb_DataFileCount >= 8 OR TEMPDBFileCount.Tempdb_DataFileCount > TEMPDBFileCount.OptimalTempdbFilecount THEN '1'
WHEN TEMPDBFileCount.OptimalTempdbFilecount > TEMPDBFileCount.Tempdb_DataFileCount THEN '0'
ELSE '1'END AS Tempdb_DataFileCount
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DataAutoGrow = 0 THEN '-1' ELSE BackupCTE.DataAutoGrow END AS DataAutoGrow
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.LogAutoGrow = 0 THEN '-1' ELSE BackupCTE.LogAutoGrow END AS LogAutoGrow
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.MaintVersion = 0 THEN '-1' ELSE BackupCTE.MaintVersion END AS MaintVersion
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.MaintVersion = 0 THEN '-1'
WHEN BackupCTE.MaintVersion = 2.02 OR BackupCTE.MaintVersion = 2.03 THEN '1'
ELSE '0' END AS FlagMaintVersion
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.DBCompatibilityLevel = 0 THEN '-1'
WHEN BackupCTE.DBCompatibilityLevel < 90 THEN '0'
ELSE '1' END AS DBCompatibilityLevel
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.FlagVersionName = 0 THEN '-1'
WHEN NOT (BackupCTE.VersionName LIKE 'Microsoft SQL Server 2005%' OR BackupCTE.VersionName LIKE 'Microsoft SQL Server 2000%') THEN '1'
ELSE '0' END AS FlagVersionName
,CASE WHEN DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL AND ComplianceReportExceptions.VLFCount = 0 THEN '-1'
ELSE BackupCTE.VLFCount END AS VLFCount
Into #FinalData
FROM [DBAPP].InstanceSQLDtl
LEFT JOIN #BackupCTE BackupCTE ON InstanceSQLDtl.InstanceID = BackupCTE.InstanceID
LEFT JOIN [DBAPP].[SQLPatchingStandards] PatchingStds ON LTRIM(RTRIM(LEFT(VersionName, CHARINDEX('-', VersionName)-1))) = LTRIM(RTRIM(LEFT
(PatchingStds.SQLVersion,CHARINDEX('-',PatchingStds.SQLVersion)-1)))
LEFT JOIN [DBAPP].[ComplianceReportExceptions] ON ComplianceReportExceptions.InstanceName = BackupCTE.InstanceName
LEFT JOIN [DBAPP].[TEMPDBFileCount] ON InstanceSQLDtl.InstanceID = [TEMPDBFileCount].InstanceID AND Type_DESC = 'ROWS'
LEFT JOIN DBO.fnGetServiceNames() StdServiceAccount ON BackupCTE.InstanceID = StdServiceAccount.InstanceID
Where BackupCTE.[InstanceName] IS NOT NULL
ORDER BY [InstanceName]

That much string manipulation and CASE statements are just always going to be slow. Maybe you can run it as a nightly batch process into a datamart? Otherwise, here are a few tips:
Since many of your CASE statements are testing for ...InstanceName IS NULL, you can split the query in half and use UNION ALL to join together the records where it is and is not null (see example). This will remove a bunch of CASE checks.
Don't use WHERE IN('SA') if there's only one item, use not-equal (<>) instead.
If at all possible, avoid doing string manipulation in a JOIN condition (...PatchingStds ON LTRIM(RTRIM(LEFT(VersionName...). Try to store those fields somewhere, either in a dedicated column or as persisted, computed columns. That way you can put in index on that field to make the join much faster.
Have indexes on the join fields where possible, subject to many factors, but mostly just don't have too many indexes on a single table because that will slow down INSERT statements.
SELECT DISTINCT
BackupCTE.[InstanceName]
, EnvironmentType = CASE WHEN ComplianceReportExceptions.EnvironmentType = 0 THEN '-1' ELSE CONVERT(VARCHAR, BackupCTE.EnvironmentType) END
, [InstanceStatus] = CASE WHEN ComplianceReportExceptions.InstanceStatus = 0 THEN '-1' ELSE CONVERT(VARCHAR,BackupCTE.InstanceStatus) END
, BackupCTE.[BackupShare]
, DatabaseOwner =
CASE WHEN ComplianceReportExceptions.DatabaseOwner = 0 THEN '-1'
WHEN ISNULL(BackupCTE.IsMirroringEnabled,0) = 0
AND BackupCTE.DatabaseOwner <> 'SA'
AND BackupCTE.DatabaseStatus = 'Normal'
AND BackupCTE.DatabaseReadOnly = 0
AND ISNULL(BackupCTE.IsDatabaseSnapshot,0) = 0
THEN '0'
ELSE '1'
END
-- Etc...
INTO #FinalData
FROM [DBAPP].InstanceSQLDtl
LEFT JOIN #BackupCTE BackupCTE ON InstanceSQLDtl.InstanceID = BackupCTE.InstanceID
LEFT JOIN [DBAPP].[SQLPatchingStandards] PatchingStds ON LTRIM(RTRIM(LEFT(VersionName, CHARINDEX('-', VersionName)-1))) = LTRIM(RTRIM(LEFT
(PatchingStds.SQLVersion,CHARINDEX('-',PatchingStds.SQLVersion)-1)))
LEFT JOIN [DBAPP].[ComplianceReportExceptions] ON ComplianceReportExceptions.InstanceName = BackupCTE.InstanceName
LEFT JOIN [DBAPP].[TEMPDBFileCount] ON InstanceSQLDtl.InstanceID = [TEMPDBFileCount].InstanceID AND Type_DESC = 'ROWS'
LEFT JOIN DBO.fnGetServiceNames() StdServiceAccount ON BackupCTE.InstanceID = StdServiceAccount.InstanceID
WHERE BackupCTE.[InstanceName] IS NOT NULL
AND DBAPP.ComplianceReportExceptions.InstanceName IS NOT NULL
--****************
UNION ALL
--****************
SELECT DISTINCT
BackupCTE.[InstanceName]
, EnvironmentType = CONVERT(VARCHAR,BackupCTE.EnvironmentType)
, [InstanceStatus] = CONVERT(VARCHAR,BackupCTE.InstanceStatus)
, BackupCTE.[BackupShare]
, DatabaseOwner =
CASE
WHEN ISNULL(BackupCTE.IsMirroringEnabled,0) = 0
AND BackupCTE.DatabaseOwner <> 'SA'
AND BackupCTE.DatabaseStatus = 'Normal'
AND BackupCTE.DatabaseReadOnly = 0
AND ISNULL(BackupCTE.IsDatabaseSnapshot,0) = 0
THEN '0'
ELSE '1'
END
-- Etc...
INTO #FinalData
FROM [DBAPP].InstanceSQLDtl
LEFT JOIN #BackupCTE BackupCTE ON InstanceSQLDtl.InstanceID = BackupCTE.InstanceID
LEFT JOIN [DBAPP].[SQLPatchingStandards] PatchingStds ON LTRIM(RTRIM(LEFT(VersionName, CHARINDEX('-', VersionName)-1))) = LTRIM(RTRIM(LEFT
(PatchingStds.SQLVersion,CHARINDEX('-',PatchingStds.SQLVersion)-1)))
LEFT JOIN [DBAPP].[ComplianceReportExceptions] ON ComplianceReportExceptions.InstanceName = BackupCTE.InstanceName
LEFT JOIN [DBAPP].[TEMPDBFileCount] ON InstanceSQLDtl.InstanceID = [TEMPDBFileCount].InstanceID AND Type_DESC = 'ROWS'
LEFT JOIN DBO.fnGetServiceNames() StdServiceAccount ON BackupCTE.InstanceID = StdServiceAccount.InstanceID
WHERE BackupCTE.[InstanceName] IS NOT NULL
AND DBAPP.ComplianceReportExceptions.InstanceName IS NULL
--****************
ORDER BY [InstanceName]

Below are the possibilities which causes to degrade the performance of an query,
Do not convert colum value at on clause instead of this create a separate colum and pre-populated the conversion, if you use conversion
it prohibit using indexes to search records in table.
Use with(nolock)
Distinct & order by are costly operations to the query , if you don’t required remove it from query.

Related

Issue with >= in the WHERE clause

I'm at my whit's end with this one, frustrated because I'm sure it's something simple and I need a second set of eyes. I've tried this several different ways and I continue to run into an issue where the query will run for a full 24 hours with no results...
I've narrowed the issue down to this section of the query:
WHERE sub.[Savings (%)] >= 10
I ran into so many issues that I ended up nesting the entire query into a sub query, trying to take most of my calculations out of the "Where" clause, but to no effect.
This is all part of a much larger query, so I'll post the abbreviated portion that is relevant.
Here's the very beginning of the query:
SELECT *
FROM
(
SELECT
LD.Region
,DM.ShortName AS DM
,D.Lcode
,LD.locationname
,D.UnitID
,D.dPlaced
,D.dCancelled
,D.sRentalType
,D.[Quoted Rate]
,Calcs.MinStdRate AS [Current Rate]
,-(Calcs.MinStdRate - D.[Quoted Rate]) AS [Savings ($)]
,((-(Calcs.MinStdRate - D.[Quoted Rate]))/NULLIF(D.[Quoted Rate],0))*100 AS [Savings (%)]
,D.sPlanName
,Calcs.[# Vacant]
FROM...
Then this is the WHERE clause at the very end of the query that causes the issue. The entire query beneath "SELECT * FROM" (shown up above) is called "Sub":
) AS sub
WHERE sub.[Savings (%)] >= 10
AND sub.[Current Rate] <> 0
AND sub.[Quoted Rate] <> 0
When I notate "sub.[Savings (%)] >= 10 AND" out of the query, the whole thing runs in about 5 seconds. With it, it runs for hours on end and never produces results...
What am I missing?
Updating to show whole query per request:
SELECT *
FROM
(
SELECT
LD.Region
,DM.ShortName AS DM
,D.Lcode
,LD.locationname
,D.UnitID
,D.dPlaced
,D.dCancelled
,D.sRentalType
,D.[Quoted Rate]
,Calcs.MinStdRate AS [Current Rate]
,-(Calcs.MinStdRate - D.[Quoted Rate]) AS [Savings ($)]
,CAST(((-(Calcs.MinStdRate - D.[Quoted Rate]))/NULLIF(D.[Quoted Rate],0))*100 AS DECIMAL (18,2)) AS [Savings (%)]
,D.sPlanName
,Calcs.[# Vacant]
FROM
(SELECT
s.sLocationCode AS lcode
,w.dPlaced
,L.dLease
,u.UnitID
,CASE
WHEN w.dCancelled IS NOT NULL THEN w.dCancelled
WHEN (w.dCancelled IS NULL AND w.dExpires <GETDATE()) THEN w.dExpires
ELSE NULL
END AS dCancelled
,CASE
WHEN (w.dCancelled IS NOT NULL OR w.dExpires <GETDATE()) THEN 'Lost'
WHEN w.QTRentalTypeID = 3 THEN 'Rented'
WHEN (w.QTRentalTypeID = 2 OR w.QTRentalTypeID = 1) THEN 'Active'
END AS sRentalType
,w.dcRate_Quoted AS 'Quoted Rate'
,c.sPlanName
,CONCAT(U.dcWidth,'x',U.dcLength) AS sSize
,UT.sTypeName
FROM CompanyDBs.dbo.waitings AS W
LEFT OUTER JOIN CompanyDBs.dbo.Ledgers AS L
ON W.LedgerID = L.LedgerID
JOIN CompanyDBs.dbo.sites AS S
ON W.SiteID = S.SiteID
JOIN CompanyDBs.dbo.units AS U
ON W.UnitID1 = U.UnitID
JOIN CompanyDBs.dbo.UnitTypes AS UT
ON U.UnitTypeID = UT.UnitTypeID
JOIN CompanyDBs.dbo.ConcessionPlans AS C
ON W.ConcessionID = C.ConcessionID
WHERE W.dCancelled < GETDATE() AND W.dCancelled >= DATEADD(DD,-60,CAST(GETDATE() AS DATE))
UNION ALL
SELECT
s.sLocationCode AS lcode
,w.dPlaced
,L.dLease
,u.UnitID
,CASE
WHEN w.dCancelled IS NOT NULL THEN w.dCancelled
WHEN (w.dCancelled IS NULL AND w.dExpires <GETDATE()) THEN w.dExpires
ELSE NULL
END AS dCancelled
,CASE
WHEN (w.dCancelled IS NOT NULL OR w.dExpires <GETDATE()) THEN 'Lost'
WHEN w.QTRentalTypeID = 3 THEN 'Rented'
WHEN (w.QTRentalTypeID = 2 OR w.QTRentalTypeID = 1) THEN 'Active'
END AS sRentalType
,w.dcRate_Quoted AS 'Quoted Rate'
,c.sPlanName
,CONCAT(U.dcWidth,'x',U.dcLength) AS sSize
,UT.sTypeName
FROM CompanyDBs1.dbo.waitings AS W
LEFT OUTER JOIN CompanyDBs1.dbo.Ledgers AS L
ON W.LedgerID = L.LedgerID
JOIN CompanyDBs1.dbo.sites AS S
ON W.SiteID = S.SiteID
JOIN CompanyDBs1.dbo.units AS U
ON W.UnitID1 = U.UnitID
JOIN CompanyDBs1.dbo.UnitTypes AS UT
ON U.UnitTypeID = UT.UnitTypeID
JOIN CompanyDBs1.dbo.ConcessionPlans AS C
ON W.ConcessionID = C.ConcessionID
WHERE W.dCancelled < GETDATE() AND W.dCancelled >= DATEADD(DD,-60,CAST(GETDATE() AS DATE))) AS D
LEFT OUTER JOIN
(SELECT
P.SiteID
,P.sLocationCode
,P.UnitID
,p.UnitCODE
,groupeddata.[# Vacant]
,GroupedData.MinStdRate
FROM
(SELECT
S2.sLocationCode
,S2.SiteID
,R2.UnitID
,CONCAT(S2.sLocationCode
,'-'
,S2.sSiteName
,' '
,R2.stypename
,' '
,CASE WHEN R2.iFloor > 1 THEN 'Up ' WHEN R2.ifloor < 1 THEN 'Down ' WHEN R2.ifloor = 1 THEN '1 ' END
,CASE WHEN R2.bPower = 1 THEN 'Power ' ELSE 'No Power ' END
,CASE WHEN R2.bClimate = 1 THEN 'CC ' ELSE 'No CC ' END
,CASE WHEN R2.bInside = 1 THEN 'In ' ELSE 'Out ' END
,CASE WHEN R2.bAlarm = 1 THEN 'Alarm ' ELSE 'No Alarm ' END
,CAST(R2.dcWidth AS FLOAT)
,'x'
,CAST(R2.dcLength AS FLOAT)) AS UnitCODE
FROM Operations.dbo.RentRoll AS R2
JOIN
(
SELECT *
FROM CompanyDBs.dbo.sites
UNION ALL
SELECT *
FROM CompanyDBs1.dbo.sites
) AS S2
ON R2.siteid = S2.SiteID
WHERE
R2.ddeleted is NULL
AND R2.bRentable = 1
AND R2.brented = 0 ) AS P
JOIN
(
SELECT
S.SiteID
,s.sLocationCode
,UnitCode.UnitCODE
,SUM(CASE
WHEN R.brented = 1 THEN 0
ELSE 1
END) AS [# Vacant]
,MIN(R.dcStdRate) AS MinStdRate
FROM Operations.dbo.RentRoll AS R
JOIN
(
SELECT *
FROM CompanyDBs.dbo.sites
UNION ALL
SELECT *
FROM CompanyDBs1.dbo.sites
) AS S
ON R.siteid = S.SiteID
JOIN
(
SELECT
S1.SiteID
,UnitID
,CONCAT(S1.sLocationCode
,'-'
,S1.sSiteName
,' '
,R1.stypename
,' '
,CASE WHEN R1.iFloor > 1 THEN 'Up ' WHEN R1.ifloor < 1 THEN 'Down ' WHEN R1.ifloor = 1 THEN '1 ' END
,CASE WHEN R1.bPower = 1 THEN 'Power ' ELSE 'No Power ' END
,CASE WHEN R1.bClimate = 1 THEN 'CC ' ELSE 'No CC ' END
,CASE WHEN R1.bInside = 1 THEN 'In ' ELSE 'Out ' END
,CASE WHEN R1.bAlarm = 1 THEN 'Alarm ' ELSE 'No Alarm ' END
,CAST(R1.dcWidth AS FLOAT)
,'x'
,CAST(R1.dcLength AS FLOAT)) AS UnitCODE
FROM Operations.dbo.RentRoll AS R1
JOIN
(
SELECT *
FROM CompanyDBs.dbo.sites
UNION ALL
SELECT *
FROM CompanyDBs1.dbo.sites
) AS S1
ON R1.siteid = S1.SiteID
) AS UnitCode
ON CONCAT(R.siteid, R.unitid) = CONCAT(UnitCode.siteid,UnitCode.UnitID)
WHERE
s.sLocationCode <> 'L003'
AND s.sLocationCode <> 'L021'
AND s.sLocationCode <> 'LSETUP'
AND s.sLocationCode <> 'LTRAIN'
AND R.bRented = 0
GROUP BY s.siteid, s.slocationcode, UnitCode.UnitCODE
) AS GroupedData
ON P.UnitCODE = GroupedData.UnitCODE
) AS Calcs
ON CONCAT(D.lcode,D.unitid) = CONCAT(Calcs.slocationcode,Calcs.unitid)
JOIN operations.dbo.westport_locationdata AS LD
ON D.lcode = ld.lcode
JOIN operations.dbo.Westport_DMs AS DM
ON LD.DMID = DM.DMID
) AS sub
WHERE sub.[Savings (%)] >= CAST(10.0 AS DECIMAL (18,2))
AND sub.[Current Rate] <> 0
AND sub.[Quoted Rate] <> 0
Unfortunately you are posting not the whole query. I could image that some indexes are missing.
I give you the strong advice to run your query in SQL Server Management Studio with the option "Query" -> "Include Actual Execution Plan" checked.
With this, SSMS will execute the query and tell you afterwards if indexes are missing and how much you could improve by setting them. You will get also a picture oh how the query is running.
Cast your where clause filter value WHERE sub.[Savings (%)] >= cast(10.0 as decimal(18,2)) so there isn't an implicit conversion from int to decimal.
https://learn.microsoft.com/en-us/sql/t-sql/data-types/data-type-conversion-database-engine?view=sql-server-ver15#:~:text=Implicit%20conversions%20are%20not%20visible,converts%20to%20date%20style%200.

Is there a way of pinpointing which line of code has a divide by zero error?

I am encountering a Divide by zero error, starting at where the SELECT statement begins at, but not sure where exactly the error is. I have placed NULLIF( ,0) where there is division commands, but still returning the divide by zero error. Is there a way of pinpointing exactly where the error is triggered?
drop table #tempMAINA
SELECT a.COUNTRY_IBS
--,a.[List_Price_Code] AS "LPC"
,a.[Item_Number]
--,b.COUNTRY_IBS
--,b.[Price_list]
--,b.[Item_Number]
,Item.Item_Desc_English AS "Item_Description"
,ITEM.Product_Manager_Name AS "Product_Manager"
--,PMCD.Category_Director
,ITEM.Manufacturer
,ITEM.Manufacturer_Desc
,ITEM.Brand
,ITEM.Brand_Desc
,CMT.NAME_PRDUCT_CLASS_LEVEL_2 AS "CMT_LEVEL_2"
,ITEM.PPG_Code
,ITEM.PPG_Desc
,TLPC.[PY_Standard_List] AS "2019_Standard_List_LC"
,TLPC.Standard_List AS "2020_Standard_List_LC"
,TLPC.Standard_List*FX.Exchange_Rate AS "2020_Standard_List_USD"
,sc2020.Standard_Cost AS "2020_Standard_Cost_LC"
,sc2020.Standard_Cost*FX.Exchange_Rate AS "2020_Standard_Cost_USD"
,(TLPC.[Standard_List]-sc2020.[Standard_Cost]) AS "2020_Margin_per_Unit_LC"
,1-sc2020.[Standard_Cost]/NULLIF(TLPC.[Standard_List],0) AS "Margin_as_%_of_Stan_List_LC"
--,c.[Conversion_factor] AS "Conv"
,CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END AS "ASP_USD"
,CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN sc2020.[Standard_Cost]*FX.Exchange_Rate
ELSE (TSC.[LTM_Cost_USD])/NULLIF(tqc.[LTM_Qty],0) END AS "ASCost_USD"
,CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List *FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END
-
CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN sc2020.[Standard_Cost]*FX.Exchange_Rate
ELSE (TSC.[LTM_Cost_USD])/NULLIF(tqc.[LTM_Qty],0) END AS Margin_per_Unit
,1- CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN sc2020.[Standard_Cost]*FX.Exchange_Rate
ELSE (TSC.[LTM_Cost_USD])/NULLIF(tqc.[LTM_Qty],0) END
/CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END AS "Margin_at_ASP_as_%_of_ASP"
,(1-(CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END)
/NULLIF(TLPC.Standard_List*FX.Exchange_Rate,0)) AS "ASP_Discount_%"
,CASE WHEN TSC.[LTM_Sales_USD] > 0
THEN 'Y' ELSE 'N' END AS "Selling_History_Y/N"
--,c.[Conversion_factor] AS "QDP_Quantity_Limit"
,CASE WHEN [Number_of_Orders] IS NULL
THEN 0
ELSE [Avg_Num_Units_per_Order] END AS "Avg. # Units per Order"
--,CASE WHEN [Avg_Num_Units_per_Order] IS NULL THEN c.[Conversion_factor]
--WHEN [Avg_Num_Units_per_Order] > c.[Conversion_factor] THEN CEILING([Avg_Num_Units_per_Order]/c.[Conversion_factor])
--*c.[Conversion_factor]
--ELSE c.[Conversion_factor] END AS "Adjusted_QDP_Quantity_Limit"
,-((CASE WHEN [Number_of_Orders] IS NULL
THEN 0
ELSE [Avg_Num_Units_per_Order] END)
-- /
--CASE WHEN [Avg_Num_Units_per_Order] IS NULL THEN c.[Conversion_factor]
-- WHEN [Avg_Num_Units_per_Order] > c.[Conversion_factor] THEN CEILING([Avg_Num_Units_per_Order]/c.[Conversion_factor])
-- *c.[Conversion_factor]
-- ELSE c.[Conversion_factor] END)
+
(CASE WHEN (LTM_Qty-PTM_Qty)/NULLIF(LTM_Qty+PTM_Qty,0) IS NULL
THEN 0
ELSE (LTM_Qty-PTM_Qty)/NULLIF(LTM_Qty+PTM_Qty,0) END +1)/2)/2 + 1 AS "GrowthNearQtyBreak"
,CASE WHEN TSC.[LTM_Sales_USD] IS NULL
THEN 0
ELSE TSC.[LTM_Sales_USD] END AS "LTM_Sales_USD"
,CASE WHEN TSC.[LTM_Cost_USD] IS NULL
THEN 0
ELSE TSC.[LTM_Cost_USD] END AS "LTM_Cost_USD"
,CASE WHEN TSC.[PTM_Sales_USD] IS NULL
THEN 0
ELSE TSC.[PTM_Sales_USD] END AS "PTM_Sales_USD"
,CASE WHEN Sales_Change IS NULL
THEN 0
ELSE Sales_Change END AS "Sales_Change"
,(CASE WHEN -(TSC.[LTM_Sales_USD]-[PTM_Sales_USD])/NULLIF(TSC.[LTM_Sales_USD]+[PTM_Sales_USD],0) IS NULL
THEN 0
ELSE -(TSC.[LTM_Sales_USD]-[PTM_Sales_USD])/NULLIF(TSC.[LTM_Sales_USD]+[PTM_Sales_USD],0) END
+1)/2 AS "Sales Growth % (scaled)"
,CASE WHEN LP_Change IS NULL
THEN 0
ELSE LP_Change END AS "LP_Change"
,CASE WHEN ((TLPC.[Standard_List]-TLPC.[PY_Standard_List])
/
(TLPC.[Standard_List]+TLPC.[PY_Standard_List]) + 1)/2 IS NULL
THEN 0.5
ELSE ((TLPC.[Standard_List]-TLPC.[PY_Standard_List])
/
(TLPC.[Standard_List]+TLPC.[PY_Standard_List]) + 1)/2 END AS "List Price % Change (scaled)"
,CASE WHEN [LTM_Qty] IS NULL
THEN 0
ELSE [LTM_Qty] END AS "LTM_Qty"
,CASE WHEN [PTM_Qty] IS NULL
THEN 0
ELSE [PTM_Qty] END AS "PTM_Qty"
,CASE WHEN Qty_Change IS NULL
THEN 0
ELSE Qty_Change END AS "Qty_Change"
INTO #tempMAINA
FROM #templistandMSLP a
--LEFT JOIN #ListPrice FLP
-- ON FLP.Item_Number=a.Item_Number
-- AND FLP.Country_IBS=a.COUNTRY_IBS
-- AND FLP.RowID='1'
LEFT JOIN [DATA_IBS].[dbo].[dim_Item_ALL_COUNTRIES] ITEM with (nolock)
ON ITEM.Item_Number=a.Item_Number
AND a.COUNTRY_IBS=ITEM.Country_IBS
--LEFT JOIN [PROJECTS_EU_List_Price_Roll].[dbo].[Product_Manager_Category_Director] PMCD
-- ON PMCD.Product_Manager=ITEM.Product_Manager_Name
LEFT JOIN Projects_Price_Volume_EU.[dbo].[GWFS_DI_CMT_TAXONOMY_HIER_TB] cmt
ON cast(ITEM.Leaf_node as varchar) = cast(cmt.[ID_TAXONOMY_NODE] as varchar)
LEFT JOIN #tempPP2019 c /* Joining the Purchase Price table to limit Supplier to =10 and date's current with today */
ON a.item_number = c.Item_Number
AND a.country_ibs = c.country_ibs
LEFT JOIN [DATA_IBS].[dbo].[fact_Quantity_Dependent_List_Prices_all_all_countries] b /* Joining the QDP List Price table to exclude those items that already have QDP Pricing */
ON a.Item_Number = b.Item_Number
AND a.country_ibs = b.country_ibs
--AND a.List_Price_Code = b.Price_list
LEFT JOIN #tempQtyChange TQC
ON a.Item_Number = TQC.Sku
AND a.COUNTRY_IBS = TQC.country_IBS
LEFT JOIN #tempSalesChange TSC
ON a.Item_Number = TSC.Sku
AND a.COUNTRY_IBS = TSC.country_IBS
LEFT JOIN #tempLPChange TLPC
ON a.Item_Number = TLPC.Item_Number
AND a.COUNTRY_IBS = TLPC.country_IBS
LEFT JOIN PROJECTS_QDP.dbo.QDP_Candidates_Avg_Sales_by_PPG_Code_202005 CPPG /* Joining QDP Candidate table with PPG Code Avg. Sales for ASP for those candidates with no selling history */
ON ITEM.PPG_Code=CPPG.PPG_Code
AND ITEM.PPG_Desc=CPPG.PPG_Desc
--LEFT JOIN PROJECTS_Price_Volume_EU.dbo.Price_Volume_Cube_Master_EUROPE_TB_2018_OldSalesOrg PV
-- ON a.COUNTRY_IBS=PV.country_IBS
-- AND a.Item_Number=PV.sku
LEFT JOIN DATA_IBS.dbo.dim_Country_Defaults_ALL_COUNTRIES CD
ON a.COUNTRY_IBS=CD.Country_Code
LEFT JOIN DATA_IBS.dbo.fact_Exchange_Rates_ALL_ALL_COUNTRIES FX
ON CD.Default_Currency=FX.Currency_Code_From
AND FX.Currency_Code_To='USD'
and FX.period=202004
left join #StandardCost2020 sc2020
on a.country_ibs=sc2020.country_ibs
and a.item_number=sc2020.item_number
--left join #QDPItems as Qdp
-- on a.country_ibs=Qdp.country_ibs
-- and a.item_number=Qdp.sku
WHERE --a.List_Price_Code = '01'
--AND c.Conversion_Factor <> 1 -- will find all records with conversion factor <> 1, some of which have a QDP price, some do not
--b.Item_Number IS NULL -- will find all records without current QDP List Price
--and Qdp.sku is null -- will exclude current qdp items with sales
Item.PPG_Desc <> 'Third Party Products '
AND TLPC.Standard_List*FX.Exchange_Rate >= CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END
AND CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END
>
CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN sc2020.[Standard_Cost]*FX.Exchange_Rate
ELSE (TSC.[LTM_Cost_USD])/NULLIF(tqc.[LTM_Qty],0) END
I see only two possible places:
The bottom of this division expression could work out to zero if TSC.[LTM_Sales_USD] is zero and tqc.[LTM_Qty] is not zero:
1- CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN sc2020.[Standard_Cost]*FX.Exchange_Rate
ELSE (TSC.[LTM_Cost_USD])/NULLIF(tqc.[LTM_Qty],0) END
/CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END
Also this expression, the bottom of both the WHEN and ELSE parts could be zero if TLPC.[Standard_List]+TLPC.[PY_Standard_List] is zero (or perhaps -1, if I'm reading the order of the operations wrong):
,CASE WHEN ( (TLPC.[Standard_List]-TLPC.[PY_Standard_List])
/
(TLPC.[Standard_List]+TLPC.[PY_Standard_List]) + 1
)/2 IS NULL
THEN 0.5
ELSE ((TLPC.[Standard_List]-TLPC.[PY_Standard_List])
/
(TLPC.[Standard_List]+TLPC.[PY_Standard_List]) + 1)/2 END
Lines I found that could produce divide by zero:
"Margin_at_ASP_as_%_of_ASP"
.../CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END
either the THEN or the ELSE could result in 0.
"List Price % Change (scaled)"
CASE WHEN ((TLPC.[Standard_List]-TLPC.[PY_Standard_List])
/
(TLPC.[Standard_List]+TLPC.[PY_Standard_List]) + 1)/2 IS NULL
THEN 0.5
ELSE ((TLPC.[Standard_List]-TLPC.[PY_Standard_List])
/
(TLPC.[Standard_List]+TLPC.[PY_Standard_List]) + 1)/2 END
Both the WHEN and the ELSE could result in 0.
Side note -- did I just search for every / for you and find all the ones without nullif?
Two simple but manual tricks:
Option 1: comment out all the output fields, then uncomment them one by one and run the query until the error occurs. You should be able to find out the field or expression causing the error but it may not be the only one.
Option 2: limit your resultset with TOP 10, TOP 1000 etc until you trigger the error. Then decrement the number of records until the error goes away. It would be good to include the IDs for all the joined tables, so that you can pinpoint the records involved. And also sort by IDs. If the error occurs after ID 999 then you know the next ID (1000 or whatever) is probably where the problem begins.
I would start with option #1. When you have identified a problematic expression, output the individual fields/values separately. Everything should become clear.
If for example you notice that this expression is crashing:
,CASE WHEN TQC.[LTM_Qty] IS NULL OR TQC.[LTM_Qty]=0
THEN TLPC.Standard_List*FX.Exchange_Rate*(1-CPPG.[Discount Percentage])
ELSE (TSC.[LTM_Sales_USD])/NULLIF(tqc.[LTM_Qty],0) END AS "ASP_USD"
Then output those columns:
TQC.[LTM_Qty],
TLPC.Standard_List,
FX.Exchange_Rate,
CPPG.[Discount Percentage],
TSC.[LTM_Sales_USD]
And look at the values, in particular tqc.[LTM_Qty].

MERGE statement updates even if the data is not updated

I have a merge statement in which I'd like to update my table rows in case any of the columns have a different value. But it seems like even though most of the rows in the source table have remained intact, the MERGE statement performs an UPDATE on at least counts what it does an UPDATE.
DECLARE #SummaryOfChanges TABLE(Change VARCHAR(50));
MERGE MyTarget AS TARGET
USING MySource AS SOURCE
ON (SOURCE.customeridHash = TARGET.Id)
WHEN MATCHED AND (TARGET.IsCompany <> SOURCE.company
OR TARGET.Gender <> SOURCE.gender
OR TARGET.BirthDate <> CONVERT(DATE, SOURCE.dateofbirth)
OR TARGET.ZipCode <> SOURCE.ZipCode
OR TARGET.City <> SOURCE.City
OR TARGET.WantsEmail <> (CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END)
OR TARGET.WantsSMS <> (CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END)
OR TARGET.WantsDM <> (CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END)
OR TARGET.WantsTM <> (CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END)
OR TARGET.HasEmail <> SOURCE.HasEmail
OR TARGET.HasMobilePhoneNumber <> SOURCE.HasMobilePhoneNumber
OR TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber
OR TARGET.Created <> SOURCE.Created
OR TARGET.Updated <> SOURCE.changed)
THEN
UPDATE SET TARGET.IsCompany = SOURCE.company,
TARGET.Gender = SOURCE.gender,
TARGET.BirthDate = CONVERT(DATE, SOURCE.dateofbirth),
TARGET.ZipCode = SOURCE.ZipCode,
TARGET.City = SOURCE.City,
TARGET.WantsEmail = (CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END),
TARGET.WantsSMS = (CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END),
TARGET.WantsDM = (CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END),
TARGET.WantsTM = (CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END),
TARGET.HasEmail = SOURCE.HasEmail,
TARGET.HasMobilePhoneNumber = SOURCE.HasMobilePhoneNumber,
TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber,
TARGET.Created = SOURCE.Created,
TARGET.Updated = SOURCE.changed
WHEN NOT MATCHED BY TARGET THEN
INSERT (
Id,
IsCompany,
Gender,
BirthDate,
ZipCode,
City,
WantsEmail,
WantsSMS,
WantsDM,
WantsTM,
HasEmail,
HasMobilePhoneNumber,
HasPhoneNumber,
Created,
Updated
)
VALUES (
SOURCE.customeridHash,
SOURCE.company,
SOURCE.gender,
CONVERT(DATE, SOURCE.dateofbirth),
SOURCE.ZipCode,
SOURCE.City,
(CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END),
(CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END),
(CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END),
(CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END),
SOURCE.HasEmail,
SOURCE.HasMobilePhoneNumber,
SOURCE.HasPhoneNumber,
SOURCE.Created,
SOURCE.changed
)
WHEN NOT MATCHED BY SOURCE THEN DELETE
OUTPUT $action INTO #SummaryOfChanges;
SELECT Change, COUNT(*) CountPerChange
FROM #SummaryOfChanges
GROUP BY Change;
I do some bookkeeping at the end of the update (the final SELECT) and it seems like almost all the rows that are not new, were updated. Is this a common behavior or is there really a value amongst my <> comparison for WHEN MATCHED AND... that is updated?
Update: As suggested by one of the comments, I wrote the following test to check whether my conditions trigger an update or not:
-- TEST MERGE
select count(*)
from MyTarget TARGET join MySource SOURCE on TARGET.Id=SOURCE.customeridHash
where TARGET.IsCompany <> SOURCE.company
OR TARGET.Gender <> SOURCE.gender
OR TARGET.BirthDate <> CONVERT(DATE, SOURCE.dateofbirth)
OR TARGET.ZipCode <> SOURCE.ZipCode
OR TARGET.City <> SOURCE.City
OR TARGET.WantsEmail <> (CASE WHEN SOURCE.noemail = 0 THEN 1 ELSE 0 END)
OR TARGET.WantsSMS <> (CASE WHEN SOURCE.nosms = 0 THEN 1 ELSE 0 END)
OR TARGET.WantsDM <> (CASE WHEN SOURCE.nodirectmarketing = 0 THEN 1 ELSE 0 END)
OR TARGET.WantsTM <> (CASE WHEN SOURCE.notelemarketing = 0 THEN 1 ELSE 0 END)
OR TARGET.HasEmail <> SOURCE.HasEmail
OR TARGET.HasMobilePhoneNumber <> SOURCE.HasMobilePhoneNumber
OR TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber
OR TARGET.Created <> SOURCE.Created
OR TARGET.Updated <> SOURCE.changed;
I realised that this query returns the same number of updates. So it is somehow more about the condition that the MERGE statement. But I wonder how they trigger updates.
I think I found my own mistake, in the conditions I write:
OR TARGET.HasPhoneNumber = SOURCE.HasPhoneNumber
Which almost always renders true!

Select with Case - amalgamating results into single record

I have a query as follows
SELECT
FGB.TEMPLATE_DETAILS_REF, FGB.TEMPLATE_STRUCTURE_REF, FGB.DFEE_ELEMENT,
CASE
WHEN Condition = 'A' THEN SUM(FGS.Weighted) END AS CondA,
CASE
WHEN Condition = 'B' THEN SUM(FGS.Weighted) END AS CondB,
CASE
WHEN Condition = 'C' THEN SUM(FGS.Weighted) END AS CondC,
CASE
WHEN Condition = 'D' THEN SUM(FGS.Weighted) END AS CondD
FROM FGBlockSummary AS FGB INNER JOIN
FGSurveyItem AS FGS ON FGB.TEMPLATE_DETAILS_REF = FGS.TEMPLATE_DETAILS_REF AND FGB.TEMPLATE_STRUCTURE_REF = FGS.TEMPLATE_STRUCTURE_REF AND
FGB.DFEE_ELEMENT = FGS.DFEE_ELEMENT
GROUP BY FGB.TEMPLATE_DETAILS_REF, FGB.TEMPLATE_STRUCTURE_REF, FGB.DFEE_ELEMENT, FGS.Condition
which produces results as follows:
16 109 Ceilings NULL 14101.47 NULL NULL
16 109 Ceilings NULL NULL 227.68 NULL
How can I amalgamate the results into a single row eg
16 109 Ceilings NULL 14101.47 227.68 NULL
Thanks
Is this what you're looking for?
I moved the SUM outside of the CASEs and eliminated FGS.Condition from the GROUP BY. It'll have the side-effect of changing your NULL values to '0', but that might be tolerable?
SELECT
FGB.TEMPLATE_DETAILS_REF
,FGB.TEMPLATE_STRUCTURE_REF
,FGB.DFEE_ELEMENT
,CondA = SUM(
CASE
WHEN FGS.Condition = 'A' THEN FGS.Weighted
ELSE 0
END)
,CondB = SUM(
CASE
WHEN FGS.Condition = 'B' THEN FGS.Weighted
ELSE 0
END)
,CondC = SUM(
CASE
WHEN FGS.Condition = 'C' THEN FGS.Weighted
ELSE 0
END)
,CondD = SUM(
CASE
WHEN FGS.Condition = 'D' THEN FGS.Weighted
ELSE 0
END)
FROM
FGBlockSummary AS FGB
INNER JOIN
FGSurveyItem AS FGS
ON
FGB.TEMPLATE_DETAILS_REF = FGS.TEMPLATE_DETAILS_REF
AND FGB.TEMPLATE_STRUCTURE_REF = FGS.TEMPLATE_STRUCTURE_REF
AND FGB.DFEE_ELEMENT = FGS.DFEE_ELEMENT
GROUP BY
FGB.TEMPLATE_DETAILS_REF
,FGB.TEMPLATE_STRUCTURE_REF
,FGB.DFEE_ELEMENT;

TSQL turning these multiple CASE queries into one query

I have the following CASE queries that return 1 if they find anything, and 0 otherwise. I would like to turn these into a single query that returns 1 if any of them are true, or 0 otherwise. How can I acomplish this?
SELECT CASE WHEN count(PLACE.CODE) > 0 THEN 1 ELSE 0 END
FROM PLACE
WHERE STYLE = 'RED'
AND RULES = 'NO'
SELECT CASE WHEN count(GARDEN.AREA) > 0 THEN 1 ELSE 0 END
FROM GARDEN
WHERE PLACE = 'GROUND'
AND MAZE = '1'
SELECT CASE WHEN count(place_area.AVAILABLE_AREA) > 0 THEN 1 ELSE 0 END
FROM PLACE_AREA as place_area
INNER JOIN USED_PLACE as used_place
ON used_place.COLOR = 'RED'
AND used_place.MAKE = 'INDUSTRY'
WHERE place_area.CODE = 'FLOOR'
AND place_area.DANCE = '0'
If I understand you correctly, you can union all the result and calculate the sum, if sum > 0 then there was at least one 1
Select Case When Sum(x.col) > 0 THEN 1 ELSE 0 END from
(
SELECT CASE WHEN count(PLACE.CODE) > 0 THEN 1 ELSE 0 END as col
FROM PLACE
WHERE STYLE = 'RED'
AND RULES = 'NO'
Union All
SELECT CASE WHEN count(GARDEN.AREA) > 0 THEN 1 ELSE 0 END as col
FROM GARDEN
WHERE PLACE = 'GROUND'
AND MAZE = '1'
Union All
SELECT CASE WHEN count(place_area.AVAILABLE_AREA) > 0 THEN 1 ELSE 0 END as col
FROM PLACE_AREA as place_area
INNER JOIN USED_PLACE as used_place
ON used_place.COLOR = 'RED'
AND used_place.MAKE = 'INDUSTRY'
WHERE place_area.CODE = 'FLOOR'
AND place_area.DANCE = '0'
) x
SELECT
CASE
WHEN
EXISTS(
SELECT TOP 1 1
FROM PLACE
WHERE STYLE = 'RED'
AND RULES = 'NO'
AND count(PLACE.CODE) > 0
)
OR EXISTS (
SELECT TOP 1 1
FROM GARDEN
WHERE PLACE = 'GROUND'
AND MAZE = '1'
AND count(GARDEN.AREA) > 0
)
OR EXISTS (
SELECT TOP 1 1
FROM PLACE_AREA as place_area
INNER JOIN USED_PLACE as used_place
ON used_place.COLOR = 'RED'
AND used_place.MAKE = 'INDUSTRY'
WHERE place_area.CODE = 'FLOOR'
AND place_area.DANCE = '0'
AND count(place_area.AVAILABLE_AREA) > 0
)
THEN 1
ELSE 0
END

Resources