high number of reads in SQL Profiler but not when enabling Statistics - sql-server

I am trying to troubleshoot a procedure that has a high number of reads in SQL Profiler, but not when I enable Statistics. It is a procedure that uses paging, and I am seeing about 17k reads on page 400 for instance, and the interesting part is that sometimes when I recompile the procedure that number drops to 1000-2000 as you can see in the screenshot. Lower pages show 1000 reads, with the number increasing as I move up:
Using SET STATISTICS IO ON in SSMS shows approximately 1000 reads even when Profiler says there are 17k:
And here is part of the procedure (the #users temp table has 4000 records in it):
SELECT [temp].[UserID] ,
[temp].[UserName] ,
[temp].[FirstName] ,
[temp].[LastName] ,
[temp].[CommissionRate] ,
[temp].[PhotoURL] ,
[temp].[UserStatusID] ,
[temp].[UserStatus] ,
[temp].[ReceivesCommission] ,
[temp].[CreatedDateTimeUTC] ,
[temp].[UserTypeID] ,
[temp].[UserType] ,
[temp].[CompanyID] ,
[temp].[CompanyName] ,
[temp].[CompanyLegalName] ,
[temp].[CompanyShortName] ,
[aggregate].[EmailAddress] ,
[aggregate].[TelephoneCount] ,
[aggregate].[Telephone] ,
[aggregate].[EmailAddressCount] ,
[address].[Address1] ,
[address].[Address2] ,
[address].[City] ,
[address].[State] ,
[address].[ZipCode]
FROM ( SELECT [user].[UserID] ,
[user].[UserName] ,
[contact].[FirstName] ,
[contact].[LastName] ,
[user].[CommissionRate] ,
[user].[PhotoURL] ,
[userStatus].[UserStatusID] ,
[userStatus].[UserStatus] ,
[user].[ReceivesCommission] ,
[user].[CreatedDateTimeUTC] ,
[userType].[UserTypeID] ,
[userType].[UserType] ,
[user].[CompanyID] ,
[user].[CompanyName] ,
[user].[CompanyLegalName] ,
[user].[CompanyShortName]
FROM [#users] [user]
INNER JOIN [dbo].[UserStatus] [userStatus] ON [userStatus].[UserStatusID] = [user].[UserStatusID]
INNER JOIN [dbo].[UserType] [userType] ON [user].[UserTypeID] = [userType].[UserTypeID]
INNER JOIN [dbo].[Contact] [contact] ON [contact].[ContactID] = [user].[UserID]
AND [contact].[ContactTypeID] = 3
WHERE ( #UserName IS NULL OR [user].[UserName] LIKE '%' + #UserName + '%' )
AND ( #FirstName IS NULL OR [contact].[FirstName] LIKE '%' + #FirstName + '%' )
AND ( #LastName IS NULL OR [contact].[LastName] LIKE '%' + #LastName + '%' )
AND ( #CompanyID IS NULL OR [user].[CompanyID] = #CompanyID )
AND ( #UserStatusID IS NULL OR [user].[UserStatusID] = #UserStatusID )
ORDER BY [contact].[LastName] ,
[contact].[FirstName] ,
[user].[CompanyName] ,
[user].[UserID] DESC
OFFSET ( #PageNumber - 1 ) * #PageSize ROWS
FETCH NEXT #PageSize ROWS ONLY
) [temp]
CROSS APPLY [dbo].[fnContactDetailAggregateGetByContactID]([temp].[UserID]) [aggregate]
LEFT JOIN [dbo].[ContactAddress] [address] ON [address].[ContactID] = [temp].[UserID]
Here is the function:
CREATE FUNCTION [dbo].[fnContactDetailAggregateGetByContactID]
(
#ContactID INT
)
RETURNS #contact TABLE
(
[ContactID] INT PRIMARY KEY NOT NULL ,
[TelephoneCount] INT NULL ,
[Telephone] VARCHAR(255) NULL ,
[EmailAddressCount] INT NULL ,
[EmailAddress] VARCHAR(255) NULL
)
WITH SCHEMABINDING
AS
BEGIN
INSERT #contact
SELECT #ContactID ,
SUM(CASE WHEN [temp].[ContactDetailTypeID] = 1 THEN 1
ELSE 0
END) [TelephoneCount] ,
MAX(CASE WHEN [temp].[ContactDetailTypeID] = 1
THEN [temp].[ContactDetailValue]
END) [Telephone] ,
SUM(CASE WHEN [temp].[ContactDetailTypeID] = 3 THEN 1
ELSE 0
END) [EmailAddressCount] ,
MAX(CASE WHEN [temp].[ContactDetailTypeID] = 3
THEN [temp].[ContactDetailValue]
END) [EmailAddress]
FROM ( SELECT [detail].[ContactID] ,
[label].[ContactDetailTypeID] ,
FIRST_VALUE([detail].[ContactDetailValue]) OVER ( PARTITION BY [label].[ContactDetailTypeID] ORDER BY [detail].[Default] DESC ) [ContactDetailValue]
FROM [dbo].[ContactDetail] [detail]
INNER JOIN [dbo].[ContactDetailLabel] [label] ON [label].[ContactDetailLabelID] = [detail].[ContactDetailLabelID]
WHERE [detail].[ContactID] = #ContactID
) [temp]
RETURN
END
Any ideas what could be causing this and how I can go about fixing it?

SELECT
t.*,
ut.[userType],
us.[userStatus],
g.[EmailAddress],
g.[TelephoneCount],
g.[Telephone],
g.[EmailAddressCount],
a.[Address1],
a.[Address2],
a.[City],
a.[State],
a.[ZipCode]
FROM (
SELECT
u.*,
c.[FirstName],
c.[LastName],
u.[CommissionRate],
u.[PhotoURL],
u.[UserStatusID],
u.[ReceivesCommission],
u.[CreatedDateTimeUTC],
u.[UserTypeID],
u.[CompanyID],
u.[CompanyName],
u.[CompanyLegalName],
u.[CompanyShortName]
FROM #users u
JOIN dbo.contact c ON c.[ContactID] = u.[UserID] AND c.[ContactTypeID] = 3
WHERE
(#UserName IS NULL OR u.[UserName] LIKE '%' + #UserName + '%')
AND (#FirstName IS NULL OR c.[FirstName] LIKE '%' + #FirstName + '%')
AND (#LastName IS NULL OR c.[LastName] LIKE '%' + #LastName + '%')
AND (#CompanyID IS NULL OR u.[CompanyID] = #CompanyID)
AND (#UserStatusID IS NULL OR u.[UserStatusID] = #UserStatusID)
ORDER BY
c.[LastName],
c.[FirstName],
u.[CompanyName],
u.[UserID] DESC
OFFSET (#PageNumber - 1) * #PageSize ROWS FETCH NEXT #PageSize ROWS ONLY
) t
JOIN dbo.userStatus us ON us.[UserStatusID] = u.[UserStatusID]
JOIN dbo.userType ut ON u.[UserTypeID] = ut.[UserTypeID]
CROSS APPLY (
SELECT
COUNT(CASE WHEN [temp].[ContactDetailTypeID] = 1 THEN 1 END) AS [TelephoneCount],
MAX(CASE WHEN [temp].[ContactDetailTypeID] = 1 THEN [temp].[ContactDetailValue] END) AS [Telephone],
COUNT(CASE WHEN [temp].[ContactDetailTypeID] = 3 THEN 1 END) AS [EmailAddressCount],
MAX(CASE WHEN [temp].[ContactDetailTypeID] = 3 THEN [temp].[ContactDetailValue] END) AS [EmailAddress]
FROM (
SELECT
[detail].[ContactID],
[label].[ContactDetailTypeID],
FIRST_VALUE([detail].[ContactDetailValue]) OVER (PARTITION BY [label].[ContactDetailTypeID] ORDER BY [detail].[default] DESC) [ContactDetailValue]
FROM [dbo].[ContactDetail] [detail]
JOIN [dbo].[ContactDetailLabel] [label] ON [label].[ContactDetailLabelID] = [detail].[ContactDetailLabelID]
WHERE [detail].[ContactID] = t.[UserID]
) [temp]
) g
LEFT JOIN dbo.ContactAddress a ON a.ContactID = t.UserID
OPTION(RECOMPILE)

Related

Optimize query with multiple calls to the same table

We are creating a view as follows:
create view [dca].[CodeDescriptions_VW]
as
select distinct
ek.EmpKey
, RTRIM(CONVERT(varchar(60), abt.fdesc)) AS AboriginalTypeDescription
, RTRIM(CONVERT(varchar(60), cma.fdesc)) AS CensusMetroAreaDescription
, RTRIM(CONVERT(varchar(60), q.c_desc)) AS CobraCodeDescription
, RTRIM(CONVERT(varchar(60), ct.fdesc)) AS ConsentTypeDescription
, RTRIM(CONVERT(varchar(60), li.fdesc)) AS DirectOrIndirectDescription
, RTRIM(CONVERT(varchar(60), dt.fdesc)) AS DisabilityTypeDescription
, RTRIM(CONVERT(varchar(60), doca.fdesc)) AS DocumentADescription
FROM
dbo.hrpersnl AS h
INNER JOIN
HRActions.dbo.EmployeeKey AS ek ON RTRIM(LTRIM(UPPER(h.p_empno))) = UPPER(ek.EmpNo) COLLATE SQL_Latin1_General_CP1_CI_AS
AND h.p_company = ek.Company COLLATE SQL_Latin1_General_CP1_CI_AS
LEFT OUTER JOIN
dbo.hrtables AS abt ON abt.ftable = ''AL'' AND RTRIM(h.p_abotype) = RTRIM(abt.code)
LEFT OUTER JOIN
dbo.hrtables AS cma ON cma.ftable = ''CM'' AND RTRIM(h.p_cma) = RTRIM(cma.code)
LEFT OUTER JOIN
dbo.hrtables AS ct ON ct.ftable = ''CS'' AND RTRIM(h.p_constype) = RTRIM(ct.code)
LEFT OUTER JOIN
dbo.hrtables AS li ON li.ftable = ''IN'' AND RTRIM(h.p_laborind) = RTRIM(li.code)
LEFT OUTER JOIN
dbo.hrtables AS dt ON dt.ftable = ''DI'' AND RTRIM(h.p_distype) = RTRIM(dt.code)
LEFT OUTER JOIN
dbo.hrtables AS doca ON doca.ftable = ''I2'' AND RTRIM(h.p_doca) = RTRIM(doca.code)
I am wondering if there is a more efficient way to reference the same table (dbo.hratables) multiple times. As is, this is a very costly view (there are actually about 3 dozen different 'Descriptions' that we need to query, I have only shown a few).
While not ideal, perhaps you could create an in-line TVF and use that vs all the joins.
Something like:
CREATE FUNCTION dbo.HRDescription (
#ftable VARCHAR(2), #code VARCHAR(50), #field VARCHAR(50)
)
RETURNS TABLE
AS
RETURN
(
SELECT RTRIM( CONVERT( VARCHAR(60),
CASE
WHEN #field = 'c_desc' THEN c_desc
ELSE fdesc
END ) ) AS [Value]
FROM dbo.hrtables
WHERE
ftable = #ftable AND RTRIM( code ) = #code
)
GO
And then modify your query:
SELECT DISTINCT
ek.EmpKey
, ( SELECT [Value] FROM dbo.HRDescription( 'AL', h.p_abotype, 'fdesc' ) ) AS AboriginalTypeDescription
, ( SELECT [Value] FROM dbo.HRDescription( 'CM', h.p_cma, 'fdesc' ) ) AS CensusMetroAreaDescription
, ( SELECT [Value] FROM dbo.HRDescription( 'CS', h.p_constype, 'fdesc' ) ) AS ConsentTypeDescription
, ( SELECT [Value] FROM dbo.HRDescription( 'IN', h.p_laborind, 'fdesc' ) ) AS DirectOrIndirectDescription
, ( SELECT [Value] FROM dbo.HRDescription( 'DI', h.p_distype, 'fdesc' ) ) AS DisabilityTypeDescription
, ( SELECT [Value] FROM dbo.HRDescription( 'I2', h.p_doca, 'fdesc' ) ) AS DocumentADescription
FROM dbo.hrpersnl AS h
INNER JOIN HRActions.dbo.EmployeeKey AS ek
ON RTRIM(LTRIM(UPPER(h.p_empno))) = UPPER(ek.EmpNo) COLLATE SQL_Latin1_General_CP1_CI_AS
AND h.p_company = ek.Company COLLATE SQL_Latin1_General_CP1_CI_AS;
Again, not ideal, but it may save on performance over the joins.

SCD type 2 including Version Counter every time a record changes

I want a +1 counter for my slowly changing dimension DIM_Object. Every time when a record from the table PMEObject table changes, I want DIM_Object.Versie to increase by 1.
Everything about the code works fine, this can also be run without any errors. However where I have "+1 Versie", I need it to actually count and refer to the past row where it shows the actual number that it needs to add the +1 to. I don't know how to make the correct reference to the old record.
INSERT INTO DIM_Object
SELECT ObjectId
, Name
, Eff_Date
, End_Date
, Current_Flag
, Versie
FROM ( MERGE DIM_Object CM
USING PMEOBJECT CS
ON ( CM.ObjectId = CS.ObjectId )
WHEN NOT MATCHED
THEN
INSERT VALUES
( CS.ObjectId
, CS.Name
, CONVERT(CHAR(10), GETDATE() - 1, 101)
, '12/31/2199'
, 'y'
, '1'
)
WHEN MATCHED AND CM.Current_Flag = 'y'
AND ( CM.Name <> CS.Name )
THEN
UPDATE SET
CM.Current_Flag = 'n' ,
CM.End_date = CONVERT(CHAR(10), GETDATE() - 2, 101)
OUTPUT
$Action Action_Out
, CS.ObjectId
, CS.Name
, CONVERT(CHAR(10), GETDATE() - 1, 101) Eff_Date
, '12/31/2199' End_Date
, 'y' Current_Flag
, +1 Versie) AS MERGE_OUT
WHERE MERGE_OUT.Action_Out = 'UPDATE';
Where I have put "+1 Versie" I want it to actually accumulate based on the prior number of DIM_Object.Versie. Right now it will just stay '1', since I guess that it only sees NULL in the current record.
Do you have any ideas?
Kind regards,
Ad
Might this modification work for you? I have added a subquery to your [Insert Values...]
Create Table #DIM_Object
(
ObjectId Int,
[Name] NVarChar(25),
End_Date Date,
Eff_Date Date,
Current_Flag Char(1),
Versie Int
)
Insert Into #DIM_Object Values
(1,'Me','2019-01-06','2020-12-31','y',1)
Create Table #PMEObject
(
ObjectId Int,
[Name] NVarChar(25),
End_Date Date,
Eff_Date Date,
Current_Flag Char(1),
Versie Int
)
Insert Into #PMEObject Values
(2,'You','2019-01-30','2019-01-07','n',1),
(1,'Him','2019-01-06','2020-12-31','n',1)
INSERT INTO #DIM_Object
SELECT ObjectId
, Name
, Eff_Date
, End_Date
, Current_Flag
, Versie
FROM (
MERGE #DIM_Object CM
USING #PMEOBJECT CS
ON ( CM.ObjectId = CS.ObjectId )
WHEN NOT MATCHED
THEN
INSERT VALUES
( CS.ObjectId
, CS.Name
, CONVERT(CHAR(10), GETDATE() - 1, 101)
, '12/31/2199'
, 'y'
, (Select Versie From #PMEObject p Where p.ObjectId = CS.ObjectId ) + 1
)
WHEN MATCHED AND CM.Current_Flag = 'y'
AND ( CM.Name <> CS.Name )
THEN
UPDATE SET
CM.Current_Flag = 'n' ,
CM.End_date = CONVERT(CHAR(10), GETDATE() - 2, 101)
OUTPUT
$Action Action_Out
, CS.ObjectId
, CS.Name
, CONVERT(CHAR(10), GETDATE() - 1, 101) Eff_Date
, '12/31/2199' End_Date
, 'y' Current_Flag
, +1 Versie
) AS MERGE_OUT
WHERE MERGE_OUT.Action_Out = 'UPDATE';
Result:
ObjectId Name End_Date Eff_Date Current_Flag Versie
1 Me 2019-01-05 2020-12-31 n 1
2 You 2019-01-06 2199-12-31 y 2
1 Him 2019-01-06 2199-12-31 y 1
The values that are updated in the MERGE are returned as "deleted" and you can capture them in the output. OUTPUT Clause (Transact-SQL)
INSERT INTO DIM_Object
SELECT ObjectId
, Name
, Eff_Date
, End_Date
, Current_Flag
, Versie
FROM (
MERGE DIM_Object CM
USING PMEOBJECT CS
ON ( CM.ObjectId = CS.ObjectId )
WHEN NOT MATCHED THEN
INSERT VALUES
( CS.ObjectId
, CS.Name
, CONVERT(CHAR(10), GETDATE() - 1, 101)
, '12/31/2199'
, 'y'
, '1'
)
WHEN MATCHED AND CM.Current_Flag = 'y' AND ( CM.Name <> CS.Name ) THEN
UPDATE SET
CM.Current_Flag = 'n' ,
CM.End_date = CONVERT(CHAR(10), GETDATE() - 2, 101)
OUTPUT
$Action Action_Out
, CS.ObjectId
, CS.Name
, CONVERT(CHAR(10), GETDATE() - 1, 101) Eff_Date
, '12/31/2199' End_Date
, 'y' Current_Flag
, deleted.Versie + 1 /* capture the modified row data */
) AS MERGE_OUT
WHERE MERGE_OUT.Action_Out = 'UPDATE';

Select multiple columns but group by only one

Using SQL Server 2008. I have been researching this problem for days. Thought about CTE and trying to use a predicate on the problem tables.
Nothing I have tried or researched has worked so here I am. The problem is it's returning duplicate OrderID.
I've marked the problem joins.
Even tried OUTER APPLY but it caused certain searches not to work. Tried INNER APPLY then duplicates again.
The problem joins, the tables, have multiple references to OrderID.
So tblRun has multiple rows with the same OrderID showing which run it was in at and what date and so forth.
I really need suggestions from all the guru's out there.
Here is the SQL:
DECLARE #CompanyID INT = 22718,
#StartDate DATETIME = '',
#EndDate DATETIME = '',
#SalesRepID INT = NULL,
#AssignedTo INT = NULL,
#ServiceDefID INT = NULL,
#ProductName VARCHAR(512) = NULL,
#IsCCOrder BIT = NULL,
#OrderID INT = NULL,
#LocationID INT = NULL,
#SalesRepLocationID INT = NULL,
#PONum VARCHAR(150) = NULL,
#InvoiceID INT = NULL,
#IsSplitOrder BIT = NULL,
#ContactID INT = NULL,
#ContactName VARCHAR(150) = NULL,
#JobName VARCHAR(200) = NULL,
#Notes VARCHAR(MAX) = NULL,
#CompanyName VARCHAR(255) = NULL,
#DueDateFrom DATETIME = '',
#DueDateTo DATETIME = '',
#SubmitedDateFrom DATETIME = '',
#SubmitedDateTo DATETIME = '',
#IsRush BIT = NULL,
#Msg VARCHAR(1000) = NULL
--#Stages dbo.int_tbltype READONLY
DECLARE #Stages TABLE (ID INT)
--INSERT INTO #Stages (ID) VALUES (1)
DECLARE #DueDate DATETIME = NULL
SET NOCOUNT ON
DECLARE #OrderIDsTBL TABLE(OrderID INT)
IF #Msg IS NOT NULL
BEGIN
INSERT INTO #OrderIDsTBL (OrderID)
SELECT OrderID
FROM tblOrderLog
WHERE Msg LIKE '%' + #Msg + '%'
END
IF #OrderID IS NOT NULL
BEGIN
INSERT INTO #OrderIDsTBL (OrderID)
VALUES (#OrderID)
END
DECLARE #OderIDsCnt INT = (SELECT COUNT(OrderID) FROM #OrderIDsTBL)
DECLARE #StageCnt INT = (SELECT COUNT(ID) FROM #Stages)
SELECT
o.OrderID,
o.CompanyID,
co.Name AS CompanyName,
o.ContactID,
o.JobName,
p.FirstName + ' ' + p.LastName AS ContactName,
p2.FirstName + ' ' + p2.LastName AS SalesRep,
o.DueDate,
CASE WHEN MAX(oi.PriorityService) > 0 THEN 1 ELSE 0 END AS IsRush,
ISNULL(s.StageID, 0) AS StageID,
o.Notes, r.SubmittedComplete,
dbo.fOrderRunLocationCSVByOrderID(o.OrderID) AS LocationCSV,
(SELECT
STUFF((SELECT DISTINCT ' ' + st.Name + '<br />' FROM tblStage st
INNER JOIN tblOrderItem oi ON oi.OrderID = o.OrderID
INNER JOIN tblRun r ON r.OrderItemID = oi.OrderItemID
INNER JOIN tblStage s ON s.StageID = r.StageID
LEFT JOIN tblRunService rs ON rs.RunID = r.RunID
WHERE (s.StageID = st.StageID)
AND (rs.AssignedTo = #AssignedTo OR #AssignedTo IS NULL)
FOR XML PATH(''), TYPE).value('.','VARCHAR(max)'), 1, 1, ''))
AS Stages,
Row_Number() Over(Order By o.OrderID Desc) As RowNum
FROM
tblOrder o
INNER JOIN
tblCompany co ON co.CompanyID = o.CompanyID
INNER JOIN
tblParty p ON p.PartyID = o.ContactID
-------- PROBLEM JOINS ------------
LEFT JOIN
tblOrderItem oi ON oi.OrderID = o.OrderID
LEFT JOIN
tblRun r ON r.OrderItemID = oi.OrderItemID
LEFT JOIN
tblService srv ON srv.OrderItemID = oi.OrderItemID
-------- END PROBLEM JOINS ------------
LEFT JOIN
tblStage s ON s.StageID = r.StageID
LEFT JOIN
tblParty p2 ON p2.PartyID = o.SalesRepID
LEFT JOIN
tblEmployee e ON e.EmployeeID = o.SalesRepID
LEFT JOIN
tblShipTo st ON o.ShipToID = st.ShipToID
WHERE
(#CompanyID IS NULL OR (o.CompanyID = #CompanyID )) AND
(#IsCCOrder IS NULL OR (ISNULL(o.IsCreditCardOrder, 0) = #IsCCOrder )) AND
(#SalesRepID IS NULL OR o.SalesRepID = #SalesRepID) AND
(#ServiceDefID IS NULL OR (srv.ServiceDefID = #ServiceDefID)) AND
(#ProductName IS NULL OR (oi.Name LIKE '%' + #ProductName + '%')) AND
(#IsSplitOrder IS NULL OR (#IsSplitOrder = 1 AND oi.SplitOrderID IS NOT NULL)) AND
(
(#StartDate = '' OR #EndDate = '') OR
(#StartDate >= CreatedDate AND #EndDate <= COALESCE(CancelledDate, ClosedDate, GetDate())) OR
(#StartDate <= COALESCE(CancelledDate, ClosedDate, GETDATE()) AND #EndDate >= COALESCE(CancelledDate, ClosedDate, GetDate()) ) OR
(#StartDate <= CreatedDate AND #EndDate >= CreatedDate )
) AND
(#LocationID IS NULL OR (#LocationID = srv.LocationID OR srv.LocationID IS NULL)) AND
(#SalesRepLocationID IS NULL OR (#SalesRepLocationID = e.LocationID OR e.LocationID IS NULL))
AND (#InvoiceID IS NULL OR o.InvoiceID = #InvoiceID )
AND (#PONum IS NULL OR o.PONum LIKE '%' + #PONum + '%')
AND (COALESCE(s.StageID, 0) IN (SELECT ID FROM #Stages) OR #StageCnt = 0)
AND (o.ContactID = #ContactID OR #ContactID IS NULL)
AND (p.FirstName + ' ' + p.LastName LIKE '%' + #ContactName + '%' OR #ContactName IS NULL)
AND (o.JobName LIKE '%' + #JobName + '%' OR #JobName IS NULL)
AND (o.Notes LIKE '%' + #Notes + '%' OR #Notes IS NULL)
AND (co.Name LIKE '%' + #CompanyName + '%' OR #CompanyName IS NULL)
AND (o.DueDate >= #DueDateFrom OR #DueDateFrom = '')
AND (o.DueDate <= #DueDateTo OR #DueDateTo = '')
AND (r.SubmittedComplete >= #SubmitedDateFrom OR #SubmitedDateFrom = '')
AND (r.SubmittedComplete <= #SubmitedDateTo OR #SubmitedDateTo = '')
AND (#IsRush = (CASE WHEN oi.PriorityService > 0 THEN 1 ELSE 0 END)
OR #IsRush IS NULL)
AND (o.OrderID IN (SELECT OrderID FROM #OrderIDsTBL) OR #OderIDsCnt = 0)
GROUP BY
o.OrderID, o.CompanyID,
co.Name,
o.ContactID, o.JobName,
p.FirstName, p.LastName, p2.FirstName, p2.LastName,
o.DueDate, o.Notes,
r.SubmittedComplete,
s.StageID
Thanks for any suggestions. I've been working on this for some time now and just can't get it working right.
It looks like you're trying to do too much with a single SELECT statement. If you want one row per unique OrderID, then don't join with the tables that have multiple rows for the same OrderID. Remove the GROUP BY clause. Use one or more separate SELECT statements to get the details from the tables that have multiple rows per OrderID.
Thanks everyone for the suggestions but I found my own solution.
With the entire sql, I placed it into a temp table.
Then used this to sort out the duplicate OrderIds....
SELECT OrderID, CompanyID, ContactID, CompanyName, JobName, ContactName,
SalesRep, DueDate, IsRush , StageID, Notes, SubmittedComplete,
LocationCSV, Stages
FROM (SELECT *, ROW_NUMBER() OVER(PARTITION BY OrderID ORDER BY OrderID DESC) 'RowRank'
FROM #SearchTbl
)sub
WHERE RowRank = 1

Performance issue because of left join and multiple where clause

Here is the procedure
create PROCEDURE [dbo].[sample1] (
#param1 varchar(20) ,
#param2 VARCHAR(5),
#param3 varchar(max) = NULL,
#param4 varchar(max) = NULL,
#param5 varchar(max) = NULL,
#param6 bit = 1,
#param7 varchar(max) = NULL,
#param8 bit = 1,
#param9 varchar(max) = NULL,
#param10 varchar(max) = NULL,
#param11 varchar(max) = NULL,
#param12 varchar(5) = 'OP',
#param13 varchar(max) = NULL,
#TOP int = 101,
#SORTFIELD varchar(20) = 'DESCRIPTION',
#SORTDIRECTION varchar(5) = 'ASC'
)
AS
BEGIN
DECLARE
#NOW VARCHAR(10)=(SELECT CONVERT(varchar(10), GETDATE(), 112)),
#PHYSNAME VARCHAR(50)='',
#PHYPARAMS CHAR(1)='N'
/*********************************/
SELECT CPPACKAGE_PARAMS, MIN(CODE) AS MinCode, MAX(CODE) AS MaxCode
INTO #SNCPPKG_PARAMS_DTLS
FROM SNCPPKG_PARAMS_DTLS
WHERE CODETYPE = 5
GROUP BY CPPACKAGE_PARAMS
SELECT *
INTO #SNCPPACKAGERL
FROM SNCPPACKAGERL
WHERE DOMDEF = #param1
--SELECT *
--INTO #SNCPPROCDEF
--FROM SNCPPROCDEF
--WHERE DOMDEF = #param1
--SELECT *
--INTO #SNCPDIAGDEF
--FROM SNCPDIAGDEF
--WHERE DOMDEF = #param1
/*********************************/
SELECT
#PHYPARAMS=[ParamaterValue]
FROM [dbo].[sntbFacilityParamaters] with(nolock)
where [ParamaterTypeId] =
(SELECT TOP 1 [ParamaterTypeId]
FROM [dbo].[sntbParamaterTypeRef] with(nolock)
where ParamaterTypeName ='Physician Specific Packages')
and facid = #param2
IF( ISNULL(#PHYPARAMS ,'N')='N')
BEGIN
SET #param11=''
END
SET NOCOUNT ON;
CREATE TABLE #tempGLT1DET (CODEFROM VARCHAR(32))
INSERT INTO #tempGLT1DET
SELECT A.CODEFROM FROM snlocGLT1DET A with(nolock)
INNER JOIN snlocGLTABLE1 B with(nolock) ON A.GLTABLE1 = B.SYSKEY
WHERE A.CODETYPE IN ('4', '5')
AND NAME = 'AMA HCPCS'
AND (B.EFF_DATE <= #NOW OR B.EFF_DATE='')
AND (B.TRM_DATE >= #NOW OR B.TRM_DATE='')
AND (B.ACTIVATION_DT <= #NOW)
if(#top>300)
BEGIN
SET #top=300
END
IF(ISNULL(#param5,'')='' )
BEGIN
SET #param6=0
END
IF( ISNULL(#param7,'')='')
BEGIN
SET #param8=0
END
SELECT * INTO #TEMPPACKAGECOMPLETE
FROM
(SELECT --TOP(#TOP)
A.SYSKEY,
A.MCOMMORD,
A.SERVTYPE,
A.DESCRIPTION,
isnull(A.some_ver,'9') as some_ver,
A.ER,
A.OUTPATIENT,
A.INPATIENT,
A.DRG,
A.EFF_DATE,
A.TRM_DATE,
A.DOMDEF,
A.FINCLASS,
A.FORMORD,
A.AUDIT,
A.ALTDESC,
A.CODE,
B.TOTALCHARGE,
--null AS PHYSNAME,
A.PHYSNAME,
--NULL AS NPI,
A.NPI,
A.CPPACKAGE_PARAMS,A.PROCCODE,A.HCPCSRATES
--,row_number() over(partition BY A.SYSKEY
-- ORDER BY A.SYSKEY) rn
FROM
(SELECT *
FROM
(SELECT --TOP(#TOP)
CPPACKAGEDEF.SYSKEY,
isnull(CPPACKAGEDEF.some_ver,'9') as some_ver,
CPPACKAGEDEF.MCOMMORD,
CPPACKAGEDEF.SERVTYPE,
CPPACKAGEDEF.DESCRIPTION AS 'DESCRIPTION',
CPPACKAGEDEF.ER,
CPPACKAGEDEF.OUTPATIENT,
CPPACKAGEDEF.INPATIENT,
CPPACKAGEDEF.DRG,
CPPACKAGEDEF.EFF_DATE,
CPPACKAGEDEF.TRM_DATE,
CPPACKAGEDEF.DOMDEF,
CPPACKAGEDEF.FINCLASS,
CPPACKAGEDEF.FORMORD,
CPPACKAGEDEF.AUDIT,
CPPACKAGEDEF.ALTDESC,
REVDET.REVCODE, --REMOVE
P.PROCCODE,REVDET.HCPCSRATES,
CODE = CASE WHEN ISNULL(params.MinCode,'') = '' THEN ''
WHEN params.MinCode = params.MaxCode THEN params.MinCode
ELSE 'Multiple' END,
-- CODE = CASE WHEN
--(SELECT count(1)
-- FROM SNCPPKG_PARAMS_DTLS d with(nolock)
-- WHERE CPPACKAGE_PARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
-- AND CODETYPE = 5) > 1 THEN 'Multiple' ELSE ISNULL(
-- (SELECT CODE
-- FROM SNCPPKG_PARAMS_DTLS d with(nolock)
-- WHERE CPPACKAGE_PARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
-- AND CODETYPE = 5), '') END,
CPPACKAGEDEF.CPPACKAGE_PARAMS,
ISNULL(SC_TYPE,'R')AS SC_TYPE
FROM SNCPPACKAGEDEF AS CPPACKAGEDEF with(nolock)
LEFT JOIN #SNCPPKG_PARAMS_DTLS AS params ON params.CPPACKAGE_PARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
LEFT JOIN #SNCPPACKAGERL REVDET ON REVDET.CPPACKAGEDEF= CPPACKAGEDEF.syskey-- and REVDET.domdef= #param1
--start:rajesh:for diag and proc
left join SNCPPROCDEF p with (nolock) on (P.CPPACKAGEDEF = CPPACKAGEDEF.syskey) and p.domdef= #param1
left join SNCPDIAGDEF d with (nolock) on (d.CPPACKAGEDEF = CPPACKAGEDEF.syskey) and d.domdef= #param1
--LEFT JOIN SNCPPACKAGERL pkgRL ON pkgRL.CPPACKAGEDEF= C.syskey
where
(
((isnull(#param5,'')='') or (d.DIAGCODE like #param5+'%'))
and
((isnull(#param7,'')='') or (p.PROCCODE like #param7+'%'))
)
AND
(
((#param13='9') AND (ISNULL(CPPACKAGEDEF.some_ver,'9')='9')) OR
((#param13='0') AND (ISNULL(CPPACKAGEDEF.some_ver,'9')='0'))
OR
(ISNULL(#param13,'')='')
)
--AND REVDET.
-- AND p.DOMDEF = #param1
--AND d.DOMDEF = #param1
AND
(
ISNULL(#param7,'')=''
OR
(
(#param12='IP' AND ISNULL(#param7,'')<>'')
--AND
--(
--( P.PROCCODE IN
-- ( SELECT DISTINCT DESTCODE FROM snVwCodeXWalk XWALK WHERE XWALK.SOURCECODE = #param10)
--)
--)
)
OR
(
((#param12='OP' OR #param12='ER') AND ISNULL(#param7,'')<>'')
AND
(
REVDET.HCPCSRATES like #param10+'%'
)
)
)
AND
(
(
( (#param5=1 AND #param8=0 )
AND
(d.SEQUENCE=1)
)
--or ISNULL(#param5,'')=''
)
OR
(
((#param8=1 AND #param6=0) AND
(p.SEQUENCE=1) )
--OR ISNULL(#param7,'')=''
)
OR
(
(
(#param5=1 )--AND ISNULL(#param5,'')<>'')
AND (#param8=1)-- AND ISNULL(#param7,'')<>'')
AND (p.SEQUENCE=1 )
AND (d.SEQUENCE=1 )
)
)
OR
(#param5=0 AND #param8=0)
)
--end:rajesh for diag and proc
--where SYSKEY = '126FAQ00249R' and
AND
(
(CPPACKAGEDEF.DESCRIPTION LIKE '%'+#param3+'%')
OR (CPPACKAGEDEF.ALTDESC LIKE '%'+#param3+'%')
OR (ISNULL(#param3,'')='')
)
AND
( (REVDET.REVCODE LIKE #param9+'%') OR (ISNULL(#param9,'')='' ))
AND( (CPPACKAGEDEF.DRG LIKE #param4+'%') OR (ISNULL(#param4,'')='') )
AND
-- ISNULL(CPPACKAGEDEF.SC_TYPE,'R')=
-- CASE WHEN #PHYPARAMS='Y'
-- THEN 'P'
--ELSE
--'R'
--end
(
(#PHYPARAMS='Y' AND CPPACKAGEDEF.SC_TYPE='P' AND ISNULL(#param11,'')<>'' )
OR
(#PHYPARAMS='Y'AND ISNULL(#param11,'')='' )
OR
(#PHYPARAMS='N'AND ISNULL(CPPACKAGEDEF.SC_TYPE,'R')='R' )
)
AND (CPPACKAGEDEF.EFF_DATE <= #NOW OR ISNULL(CPPACKAGEDEF.EFF_DATE,'')='')
AND (CPPACKAGEDEF.TRM_DATE >= #NOW OR ISNULL(CPPACKAGEDEF.TRM_DATE,'')='')
AND CPPACKAGEDEF.DOMDEF=#param1
--AND p.DOMDEF=#param1
--AND d.DOMDEF=#param1
) CPPACKAGEDEF
LEFT JOIN
(SELECT PHYSNAME,
phyPARAMS,
NPI
FROM
(SELECT DISTINCT b.PHYSNAME,
b.NPI,
cp.SYSKEY phyPARAMS,
ROW_NUMBER() OVER (PARTITION BY b.NPI,cp.SYSKEY
ORDER BY b.MDATE DESC) AS rowNum
FROM dbo.BILLPHYS b
INNER JOIN SNCPPACKAGE_PARAMS cp with(nolock) ON cp.NPI = b.NPI
WHERE ISNULL(b.NPI, '') <> '') phy
WHERE phy.rowNum=1) B ON B.phyPARAMS = CPPACKAGEDEF.CPPACKAGE_PARAMS
WHERE (CPPACKAGEDEF.SYSKEY <> ''
AND CPPACKAGEDEF.AUDIT = 'Z')
AND (CPPACKAGEDEF.DOMDEF IN (#param1))
AND (
((CPPACKAGEDEF.INPATIENT = 'Y') AND (#param12='IP'))
OR
((CPPACKAGEDEF.OUTPATIENT = 'Y') AND (ISNULL(#param12,'OP')='OP'))
OR
((#param12='ER' AND CPPACKAGEDEF.OUTPATIENT = 'Y' )AND CONVERT(INT,CPPACKAGEDEF.REVCODE) BETWEEN 450 AND 459)
)
) A
LEFT JOIN
(SELECT SUM(CONVERT(MONEY, LINECHARGE) * UNITS) AS 'TOTALCHARGE', CPPACKAGEDEF FROM
(SELECT LINECHARGE,
UNITS,
CPPACKAGEDEF
FROM #SNCPPACKAGERL with(nolock)) B
GROUP BY CPPACKAGEDEF) B ON A.SYSKEY = B.CPPACKAGEDEF
) A
-- LEFT JOIN SNCPPACKAGERL REVDET ON REVDET.CPPACKAGEDEF= A.syskey AND REVDET.DOMDEF=#param1
WHERE
--rn= 1
--AND
( (A.PHYSNAME LIKE #param11+'%') OR (ISNULL(#param11,'')='' ))
--
--select * from #TEMPPACKAGECOMPLETE
---
--SELECT count(DISTINCT SYSKEY)FROM #TEMPPACKAGE
-- gpant start
Select top (#top) * into #TEMPPACKAGE from (Select *,row_number() over(partition BY SYSKEY
ORDER BY SYSKEY) rn from #TEMPPACKAGECOMPLETE where ((
ISNULL(#param7,'')=''
OR
(
(#param12='IP' AND ISNULL(#param7,'')<>'')
AND
(
( PROCCODE IN
( SELECT DISTINCT DESTCODE FROM snVwCodeXWalk XWALK WHERE XWALK.SOURCECODE = #param10)
)
)
)
OR
(
((#param12='OP' OR #param12='ER') AND ISNULL(#param7,'')<>'')
--AND
--(
-- HCPCSRATES like #param10+'%'
--)
)
) ))t where rn =1
-- --gpant end
SELECT
--count(distinct T.SYSKEY) AS ScSyskey
T.SYSKEY AS ScSyskey,
T.DESCRIPTION AS ScDescription,
T.PHYSNAME AS ScPhysician ,
CASE WHEN ISNULL(#param12 ,'OP')='OP' THEN 'OP'
ELSE
CASE WHEN #param12='IP' THEN 'IP'
ELSE
CASE WHEN #param12='ER' THEN 'ER'
END
END
END ScPatientType,
--'I' AS ScPatientType,
T.DRG AS ScDiagnosis,
T.CODE AS ScPrimaryCdmProcedure ,
CASE WHEN P.DIAG_PRIMARYCODE='Y' THEN P.DIAGCODE ELSE NULL END AS ScPrimaryIcdDiagnosis,
CASE WHEN P.PROC_PRIMARYCODE='Y' THEN P.PROCCODE ELSE NULL END AS ScPrimaryIcdProcedure,
ISNULL(T.TOTALCHARGE, 0) AS ScAmount,
T.MCOMMORD AS ScClaimCount,
C.CODE AS ScCode,
C.CODETYPEDESC AS ScCodeType,
T.DESCRIPTION AS ScCodeDescription,
CAST(C.DATEFROM AS DATETIME) AS ScDateFrom,
CAST(C.DATETO AS DATETIME) As ScDateTo,
REVCODE.UNITS AS CdmUnits,
REVCODE.UNITSORDAYS AS CdmUnitType,
REVCODE.CPT4 AS CdmCode,
REVCODE.MODIFIERS AS CdmModifier,
REVCODE.REVCODE AS CdmRevenueCode,
REVCODE.REVDESC AS CdmDescription,
REVCODE.CHARGECODE AS CdmChargeCode,
REVCODE.LINECHARGE AS CdmPerUnitCharge,
P.DIAGCODE AS IcdDiagCode,
P.DIAG_PRIMARYCODE AS IcdDiagIsPrimary,
P.DIAGDESC AS IcdDiagDescription,
P.PROCCODE AS IcdProcCode,
P.PROC_PRIMARYCODE AS IcdProcIsPrimary,
P.PROCDESCS AS IcdProcDescription,
p.ProcedureSequence,
p.DiagSequence
FROM #TEMPPACKAGE T
LEFT JOIN
(
select distinct x.syskey as CPPACKAGEDEF,
proce.PROCCODE AS PROCCODE,
diag.DIAGCODE AS DIAGCODE,
PROCDESC.PROCDESC AS PROCDESCS ,
DIAGDESC.DIAGDESC AS DIAGDESC,
ISNULL(PROCDESC.ICD_CODE_VERSION,'ICD9Proc') as proccode_version ,
ISNULL(DIAGDESC.ICD_CODE_VERSION,'ICD9Dx') as diagcode_version, --ISNULL(p.DIAGDESC.ICD_CODE_VERSION,'ICD9Dx')
PROCDESC.VALID AS ISPROCVALID,
DIAGDESC.VALID AS ISDIAGVALID,
CASE WHEN PROCE.SEQUENCE =1 THEN 'Y' ELSE 'N' END AS PROC_PRIMARYCODE,
CASE WHEN DIAG.SEQUENCE =1 THEN 'Y' ELSE 'N' END AS DIAG_PRIMARYCODE ,
PROCE.SEQUENCE AS ProcedureSequence,
DIAG.SEQUENCE AS DiagSequence
from
--(
(
select distinct c.syskey as syskey
from snCPPACKAGEDEF C where domdef=#param1
)x
left join SNCPPROCDEF proce on (x.syskey=proce.CPPACKAGEDEF and proce.DOMDEF = #param1)
left join SNCPDIAGDEF diag on (x.syskey=diag.CPPACKAGEDEF and diag.DOMDEF = #param1)
left join SNLOCCP_DTPROC PROCDESC with(nolock) ON (proce.PROCCODE = PROCDESC.PROCCODE and PROCDESC.valid='Y' )
LEFT JOIN SNLOCCP_DTDIAG DIAGDESC with(nolock) ON (diag.DIAGCODE = DIAGDESC.DIAGCODE and DIAGDESC.valid='Y')
) P
ON T.SYSKEY = P.CPPACKAGEDEF
LEFT JOIN
VWCODEDESC AS C ON T.CPPACKAGE_PARAMS = C.CPPACKAGE_PARAMS
LEFT JOIN
(SELECT DISTINCT pkgRL.CPPACKAGEDEF, pkgRL.CHARGECODE, pkgRL.UNITS, pkgRL.UNITSORDAYS, pkgRL.SEQUENCE,
pkgRL.PERRELEVANCE, CAST(ISNULL(pkgRL.MOD1,'') + ','+ ISNULL(pkgRL.MOD2,'') + ','+ ISNULL(pkgRL.MOD3,'')+ ','+ ISNULL(pkgRL.MOD4,'') AS VARCHAR(50)) AS MODIFIERS, pkgRL.UNITWEIGHT,
ISNULL(pkgRL.REVDESC,'Procedure no longer exists!') AS REVDESC, pkgRL.HCPCSRATES,
pkgRL.REVCODE, pkgRL.LINECHARGE, pkgRL.STATCHARGE, pkgRL.CDMCHARGE,
CASE WHEN pkgRL.HCPCSRATES = '' OR pkgRL.HCPCSRATES IN (SELECT CODEFROM FROM #tempGLT1DET) THEN pkgRL.HCPCSRATES ELSE 'Invalid HCPCS Code:' + pkgRL.HCPCSRATES END AS 'CPT4'
FROM #SNCPPACKAGERL pkgRL ) revcode
ON T.SYSKEY = revcode.CPPACKAGEDEF
where
--(ISNULL(p.PROCCODE,'')<>'' OR ISNULL(p.DIAGCODE,'')<>'')
--AND
ISNULL(ISDIAGVALID,'Y')='Y' AND ISNULL(ISPROCVALID,'Y')='Y'
and
(
(
(
(T.some_ver='9' AND ISNULL(p.diagcode_version,'ICD9Dx')='ICD9Dx' )
OR
(T.some_ver='0' AND p.diagcode_version='ICD10CM')
OR
(ISNULL(P.DIAGCODE,'')='')
)
AND
(
(T.some_ver='9' AND ISNULL(p.proccode_version,'ICD9Proc')='ICD9Proc' )
OR
(T.some_ver='0' AND p.proccode_version='ICD10PCS')
OR
(ISNULL(P.PROCCODE,'')='')
)
)
OR
((ISNULL(P.DIAGCODE,'')='')OR(ISNULL(P.PROCCODE,'')='') )
)
ORDER BY CASE
WHEN UPPER(#SORTFIELD) = 'DESCRIPTION' AND
#SORTDIRECTION = 'DESC' THEN T.DESCRIPTION
END DESC,
CASE
WHEN UPPER(#SORTFIELD) = 'DESCRIPTION' AND
#SORTDIRECTION != 'DESC' THEN T.DESCRIPTION
END ASC,
CASE
WHEN UPPER(#SORTFIELD) = 'CHARGECODE' AND
#SORTDIRECTION = 'DESC' THEN
T.SYSKEY
END DESC,
CASE
WHEN UPPER(#SORTFIELD) = 'CHARGECODE' AND
#SORTDIRECTION != 'DESC' THEN
T.SYSKEY
END ASC
END
In the procedure param1 and param2 are mandatory. when I search with the rest of the params, my procedure is giving me average performance(withing 10-12 seconds). But When I search with param10 I am getting the result in 16 minutes which is unacceptable. I have tried to tweak the procedure by changing the where clause positions, implementing temp tables but did not help.
Suggest some ways which can increase the performance with only param10.
Try creating an index on REVDET.HCPCSRATES and then on snVwCodeXWalk.SOURCECODE. Try one first, then the other, then both, and see what effect it has.

Update a record after it is processed using MS SQL

I am inserting records from a table that has a column IsMatch. I have written an insert statement that works but I have run into a slight catch.
My insert record only selects the top 1 from the table where IsMatch = 2.
I need to update the record after it is inserted so that IsMatch = 3 and thus it will not be selected again.
Here is the code:
begin tran
INSERT INTO [Contact](
[Company]
, [Contact]
, [Title]
, [MailingAddress]
, [MailingCity]
, [MailingState]
, [MailingZip]
, [ShippingAddress]
, [ShippingCity]
, [ShippingState]
, [ShippingZip]
, [Phone]
, [SIC]
, [EmpSize]
, [LockedBy]
, [LastUpdated]
, [Source]
, [CreateDate]
, [ContactCategory]
, [ContactGroup]
, FirstName
, LastName
, Mar
, website
)
SELECT top 1
company
, firstname+ ' ' + lastName as contact
, contactTitle as title
, address as mailingaddress
, city as mailingcity
, state as mailingstate
, zip as mailingzip
, locationaddress as shippingaddress
, locationcity as shippingcity
, locationstate as shippingstate
, locationzip as shippingzip
, phone
, primarysic as sic
, employeeSizeRange as empsize
, 0 as lockedby
, '2015-01-19' as lastUpdated
, 'InfoUSA20141231' as source
, getdate() as createdate
, 'Cellular Telephones-Service & Repair' as contactCategory
, 'InfoUsa' as ContactGroup
, lastName
, firstname
, 'PB-NewWireless' as Mar
, website
FROM tmp_WirelessRepairListDec2014
WHERE isMatch = 2
UPDATE tmp_WirelessRepairListDec2014
SET isMatch = 3
WHERE id in (
SELECT top 1 id
FROM tmp_WirelessRepairListDec2014
WHERE isMatch = 2
)
commit tran
Try This
DECLARE #tempTable as TABLE
(
pkid bigint null
)
INSERT INTO TABLENAME
(
COL1,
COL2,
COL3
)
OUTPUT INSERTED.pkid
INTO #tempTable
SELECT COL1,COL2,COL3
FROM TABLENAME_2
Now you can use the PKID value in the #tempTable to update your record
SELECT * FROM #tempTable

Resources