Stored Procedure takes 30 seconds but Report takes 10 minutes - sql-server-2005
I am using SQL Server 2005 and I have been trying to fix this for a while now. I have tried the parameter sniffing and with recompile but neither have worked.
When executing the stored procedure, it takes 30 seconds and the report takes around 10 minutes. I'm not going to post the whole stored procedure because it is 300 lines, but I'll post the first bit of it. I am lost, and so are my coworkers as to why this is so slow.
ALTER PROCEDURE [dbo].[sp_PermitAllData]
#datey datetime
with recompile
AS
BEGIN
Set NoCount On
Declare #date datetime
Set #date = #datey
--Permit11
select
MDate,
isnull(NumbBreaker, 0) NumbBreaker,
isnull(Steel20T, 0) Steel20T,
isnull(Steel9T, 0) Steel9T,
isnull(Ductile, 0) Ductile,
isnull(IMF,0) IMF,
isnull((select sum(NumbBreaker) from Permit p
where MDate>= dateadd(month,-11,Permit.MDate) and MDate<= dateadd(month,-1,Permit.MDate)),0) NumbBreaker11,
isnull((select sum(Steel20T) from Permit p
where MDate>= dateadd(month,-11,Permit.MDate) and MDate<=dateadd(month,-1,Permit.MDate) and MDate>='10/1/2008'),0) Steel20T11,
isnull((select sum(Steel9T) from Permit p where MDate>= dateadd(month,-11,Permit.MDate) and MDate<= dateadd(month,-1,Permit.MDate)and MDate>='10/1/2008'),0) Steel9T11,
isnull((select sum(Ductile) from Permit p where MDate>= dateadd(month,-11,Permit.MDate) and MDate<= dateadd(month,-1,Permit.MDate)),0) Ductile11,
isnull((select sum(IMF) from Permit p where MDate>= dateadd(month,-11,Permit.MDate) and MDate<= dateadd(month,-1,Permit.MDate)),0) IMF11
Into #Permit11
from
Permit
where
MDate between dateadd(month,-2,#date) AND #date
--270
SELECT dateadd(month,datediff(month,0,fdate),0) Month,-1*SUM(fqty) 'A270',
(select -1*sum(fqty)
from M2MDATA01.dbo.intran t INNER JOIN
M2MDATA01.dbo.inmast m ON t.fpartno = m.fpartno INNER JOIN
M2MDATA01.dbo.jomast j ON t.ftojob = j.fjobno INNER JOIN
M2MDATA01.dbo.inmast m2 on j.fpartno=m2.fpartno and j.fpartrev=m2.frev and j.fac=m2.fac
--PEntries e ON j.fpartno = e.Sand
where dateadd(month,datediff(month,0,t.fdate),0) BETWEEN dateadd(month,-11,dateadd(month,datediff(month,0,intran.fdate),0)) and dateadd(month,-1,dateadd(month,datediff(month,0,intran.fdate),0)) AND
fdate>='6/1/2008' AND
t.ftype = 'I' AND
(m.fdescript in('TECHNISET 6435 PART 2 339749','TECHNISET F6000 PART 1 347944') OR m.fdescript LIKE 'ACTIVATOR%') AND
m2.fcusrchr2='270') 'A27011'
Into #270
FROM M2MDATA01.dbo.intran intran INNER JOIN
M2MDATA01.dbo.inmast inmast ON intran.fpartno = inmast.fpartno INNER JOIN
M2MDATA01.dbo.jomast jomast ON intran.ftojob = jomast.fjobno INNER JOIN
M2MDATA01.dbo.inmast m2 on jomast.fpartno=m2.fpartno and jomast.fpartrev=m2.frev and jomast.fac=m2.fac
-- PEntries ON jomast.fpartno = PEntries.Sand
WHERE dateadd(month,datediff(month,0,fdate),0) BETWEEN dateadd(month,-2,#date) and #date AND
intran.ftype = 'I' AND
(inmast.fdescript in('TECHNISET 6435 PART 2 339749','TECHNISET F6000 PART 1 347944') OR inmast.fdescript LIKE 'ACTIVATOR%') AND
m2.fcusrchr2='270'
GROUP BY dateadd(month,datediff(month,0,fdate),0), dateadd(month,-11,dateadd(month,datediff(month,0,intran.fdate),0)), dateadd(month,-1,dateadd(month,datediff(month,0,intran.fdate),0))
ORDER BY dateadd(month,datediff(month,0,fdate),0)
Related
Returning values from different rows in a stored procedure as different values
I have a stored procedure: `SET ANSI_NULLS ON GO SET QUOTED_IDENTIFIER ON GO ALTER PROCEDURE [ebs].[DB_Task_ONEYCRPRaport] --#startDate DATE, --#endDate DATE AS BEGIN SELECT DISTINCT CAST(A.ExternalMerchantId as varchar) "Merchant_guid", -- ok CAST(C.CreatedOn AS DATE) "Purchase_date", --ok CAST(C.CreatedOn AS TIME) "Purchase_hour", --ok C.ContractNo "Funding_reference",--ok APP.OrderNo "External_reference", --ok A.CustomerInternalId "Customer_external_code",--ok CASE WHEN I.TotalAmountToPay = 0 THEN '-' ELSE '+' END "Total_amount_symbol",--ok CASE WHEN I.TotalAmountToPay = 0 THEN I.TotalAmountToRecover ELSE I.TotalAmountToPay END "Total_amount" from ebs.Account as A JOIN ebs.FTOS_CB_Contract AS C ON A.Accountid = C.CustomerId JOIN ebs.FTOS_CB_BankAccount AS BA ON BA.FTOS_CB_BankAccountid = C.MainBankAccountId JOIN ebs.FTOS_CB_BankAccountOperation AS BAO ON BAO.BankAccountId = BA.FTOS_CB_BankAccountid JOIN Ebs.FTOS_CMB_Currency AS CU ON CU.FTOS_CMB_Currencyid = C.CurrencyId JOIN ebs.FTOS_TPM_Invoice AS I ON I.BankAccountId = BA.FTOS_CB_BankAccountid JOIN ebs.FTOS_TPM_InvoiceDetail AS ID ON ID.InvoiceId = I.FTOS_TPM_Invoiceid JOIN ebs.FTOS_BNKAP_Application AS APP ON APP.ContractId = ID.ContractId JOIN ebs.FTOS_CB_Payment AS P ON I.FTOS_TPM_Invoiceid=P.InvoiceId JOIN ebs.FTOS_BP_BankingProduct AS BP ON BP.FTOS_BP_BankingProductid=(SELECT CO.ProductId from ebs.FTOS_CB_Contract AS CO where CO.FTOS_CB_Contractid = ID.ContractId) JOIN ebs.FTOS_TPM_PreInvoiceDetail AS PID ON PID.ContractId = C.FTOS_CB_Contractid left JOIN ebs.FTOS_ONEY_ICE_Repayment as R ON P.PaymentNo = R.PaymentNo left JOIN ebs.FTOS_ONEY_ICE_Repayment_Details AS RD ON RD.FTOS_ONEY_ICE_Repaymentid = R.FTOS_ONEY_ICE_Repaymentid -- detalii plati efectuate left JOIN ebs.FTOS_ONEY_ICE_Libra_ReceivedPayments AS RP ON RP.FTOS_CB_Contractid = C.FTOS_CB_Contractid --and DATEPART(week, C.CreatedOn) = DATEPART(week, GETDATE()) take current week results END` I have another table where commissions are stored, the problem is I don't know how to select them in my stored procedure if they are on separate columns: Here is the test query: SELECT PID.* FROM [ebs].[FTOS_TPM_PreInvoiceDetail] as PID WHERE PID.Name = 'name' Basically for this example I want those values 20 and 5 to be selected in my stored procedures as two different values, how can I achieve that? I tried created another stored procedure, but I think is a very bad idea.
How to extract people who have NOT transacted since the last visit
I'm supposed to be reaching users who have NOT transacted since the configured days. I'm capturing users who HAVE transacted within X days. Not quite sure how I should get the user who have NOT transacted since the last the visit CREATE PROCEDURE [ContentPush].[GetLastVisitDateTransaction] #DaysSinceLastVisit INT, #TenantID UNIQUEIDENTIFIER AS BEGIN DECLARE #ReturnJson NVARCHAR(MAX) SET #ReturnJson = ( SELECT DISTINCT [D].[UserID] FROM [dbo].[UserInfo] D WITH(NOLOCK) INNER JOIN [Txn].[Txn] T WITH (NOLOCK) ON [D].[UserID]=[T].[UserID] INNER JOIN [Txn].[TxnPaymentResponse] TPR WITH(NOLOCK) ON [T].[TxnID] = [TPR].[TxnID] WHERE [TPR].[PaymentResponseType] = 'FINAL' AND [TPR].[PaymentResultCode] = 'approved' AND [T].[AppTenantID] = #TenantID AND ( [T].[TransactionDateTime]>= DATEADD(DD, - #DaysSinceLastVisit, GETUTCDATE()) ) AND D.IsActive = 1 FOR JSON PATH) SELECT #ReturnJson END
You can start from the users table, and use not exists to filter out those that had a transaction within the period. SELECT [D].[UserID] FROM [dbo].[UserInfo] D WHERE NOT EXISTS ( SELECT 1 FROM [Txn].[Txn] T INNER JOIN [Txn].[TxnPaymentResponse] TPR ON [T].[TxnID] = [TPR].[TxnID] WHERE [D].[UserID]=[T].[UserID] AND [TPR].[PaymentResponseType] = 'FINAL' AND [TPR].[PaymentResultCode] = 'approved' AND [T].[AppTenantID] = #TenantID AND [T].[TransactionDateTime]>= DATEADD(DD, - #DaysSinceLastVisit, GETUTCDATE()) AND D.IsActive = 1 )
SQL query running slowly - parameter sniffing
I have a simple query where I return a list of orders by date range. This query is used in a report which feeds it parameters(Site, From Date, and To Date). ALTER PROCEDURE [dbo].[Z_N_ECOM_ORDER_STATUS_DATERANGE] #Site VARCHAR(5), #FromDate DATETIME, #ToDate DATETIME AS BEGIN SET NOCOUNT ON; SELECT o.Company_Code, o.Division_Code, o.Control_Number, RTRIM(o.Customer_Purchase_Order_Number) AS Shopify_Num, CASE WHEN p.PickTicket_Number IS NULL THEN i.PickTicket_Number ELSE p.PickTicket_Number END PickTicket_Number, i.Invoice_Number, o.Date_Entered, CASE WHEN ph.packslip IS NULL AND i.invoice_number IS NULL AND P.pickticket_number IS NULL THEN 'Cancelled' WHEN ph.packslip IS NULL AND i.invoice_number IS NULL AND DATEADD(minute, 90, o.date_entered) > CURRENT_TIMESTAMP THEN 'Not Entered Yet' WHEN ph.packslip IS NULL THEN 'SHIPPED & UPLOADED' ELSE RTRIM (z.status) END Accellos_Status, b.UPS_Tracking_Number Tracking_Number FROM [JMNYC-AMTDB].[AMTPLUS].[dbo].Orders o (nolock) LEFT JOIN [JMNYC-AMTDB].[AMTPLUS].[dbo].PickTickets p (nolock) ON o.Company_Code = p.Company_Code AND o.Division_Code = p.Division_Code AND o.Control_Number = p.Control_Number LEFT JOIN [JMNYC-AMTDB].[AMTPLUS].[dbo].Invoices i (nolock) ON o.Company_Code = i.Company_Code AND o.Division_Code = i.Division_Code AND o.Control_Number = i.Control_Number LEFT JOIN [JMNYC-AMTDB].[AMTPLUS].[dbo].box b (nolock) ON o.Company_Code = b.Company_Code AND o.Division_Code = b.Division_Code AND i.PickTicket_Number = b.PickTicket_Number LEFT JOIN pickhead ph (nolock) ON p.PickTicket_Number = ph.packslip LEFT JOIN Z_Status z (nolock) ON ph.PROCSTEP = z.procstep WHERE o.Company_Code = LEFT(#Site, 2) AND o.Division_Code = RIGHT(#Site, 3) AND o.Customer_Number = 'ecom2x' AND o.Date_Entered BETWEEN #FromDate AND DATEADD(dayofyear, 1, #ToDate) ORDER BY o.date_entered DESC END The problem with this query is that it takes way too long and the problem lines are WHERE o.Company_Code = LEFT(#Site, 2) AND o.Division_Code = RIGHT(#Site, 3) The format of the variable site is something like '09001' or '03001' where the left side is the company and the right side is the division Because when I run this query with hard-coded values, it runs pretty much instantaneously. When I use the parameters, it takes minutes. So I looked it up and I discovered about parameter sniffing. So I added the following line after the begin statement. DECLARE #LocalSite VARCHAR(5) = CAST(#Site AS VARCHAR(5)) However, it still runs extremely slow. My new where statement would be WHERE o.Customer_Number = 'ecom2x' AND o.Date_Entered BETWEEN #FromDate AND DATEADD(dayofyear, 1, #ToDate) AND ((#LocalSite = '00000') OR (O.Company_Code = LEFT(#LocalSite, 2) AND O.Division_Code = RIGHT(#LocalSite, 3))) order by o.date_entered desc* I also want the user to have the functionality of selecting all sites which will make the site variable be '00000' and thus it shouldn't run the company/division code check. This current where statement makes the query run very slow. Does anyone know what I am doing wrong?
Can you try to avoid using LEFT() and RIGHT() by declaring few variables and assigning values to those variables and then using them in the SELECT statement? a hint OPTIMIZED FOR UNKNOWN to avoid parameter sniffing: option (OPTIMIZE FOR (#p1 UNKNOWN, #p2 UNKNOWN)) Where p1 and p2 those two variables mentioned above I also want the user to have the functionality of selecting all sites which will make the site variable be '00000' and thus it shouldn't run the company/division code check. This current where statement makes the query run very slow. This can be optimized by replacing current SELECT with IF statement that uses two SELECTs. If value is 00000 just avoid to check on company and division, else run the same select but with those extra checks Another striking thing is querying linked server objects with further join to local tables. Consider to split this into a separate step, for instance by storing data in temporary table (not a table variable!) as intermediate result. Then temp table to be joined with local objects. This can improve accuracy of query plan because of better estimates.
Did you try taking left and right values of#site parameter in two different variables and using those variables in SP. For eg. Declare #compcode as varchar(2) Declare #divcode as varchar(3) Set #compcode=LEFT(#Site, 2) Set #divcode=RIGHT(#Site, 3) Your where condition WHERE o.Company_Code = #compcode AND o.Division_Code = #divcode
Grouping and Pipe delimiter (Newbee) SQL Server 2008 R2
I created this script: SELECT Distinct rtrim(Insurances.EligibilityPayorNumber) as InsurancePayorCode , rtrim(ContractFacilityProviders.NPI) as ProviderID , rtrim(PatientInsuranceProfiles.Insurance1PolicyNumber) as SubscriberInsuranceID , rtrim(PatientInsuranceProfiles.Insurance1PolicyGroupNumber) as SubscriberGroupNumber , rtrim(PatientDemographics.firstname) as SubscriberFirstName , rtrim(PatientDemographics.MiddleInitial) as SubscriberMiddleInitial , rtrim(PatientDemographics.Lastname) as SubscriberLastName , rtrim(PatientDemographics.sex) as Gender , rtrim(PatientDemographics.DateofBirth) as DOB , ScheduleEntry.ScheduleDate as DateofService , PatientDemographics.AccountNumber as TrackingID FROM ScheduleEntry LEFT JOIN PatientDemographics ON ScheduleEntry.PatientAccount = PatientDemographics.AccountNumber LEFT JOIN Reasons ON ScheduleEntry.ReasonCode = Reasons.ReasonCode LEFT JOIN Providers ON ScheduleEntry.ResourceCode = Providers.MedStarProviderIdentifier LEFT JOIN Facilities ON ScheduleEntry.FacilityCode = Facilities.MedStarFacilityIdentifier LEFT JOIN [john-pc\sqlexpress].[Global].[dbo].[PatientStatuses] TAB2 on ScheduleEntry.PatientStatus = TAB2.PatientStatusCode LEFT JOIN AddedResource ON ScheduleEntry.ResourceCode = AddedResource.AddedResourceCode LEFT JOIN Caregiver ON ScheduleEntry.ResourceCode = Caregiver.CaregiverCode LEFT JOIN ReasonScripts ON ScheduleEntry.ReasonCode = ReasonScripts.Reasoncode LEFT JOIN Scripts on Reasonscripts.Scriptcode = Scripts.ScriptCode LEFT JOIN PatientInsuranceProfiles ON ScheduleEntry.PatientAccount = PatientInsuranceProfiles.PatientAccountNumber LEFT JOIN Insurances ON PatientInsuranceProfiles.Insurance1Mnemonic = Insurances.Mnemonic LEFT JOIN ContractFacilityProviders ON PatientDemographics.PrimaryPhysician = ContractFacilityProviders.ProviderIdentifier WHERE ScheduleEntry.ScheduleDate >= getdate() and ScheduleEntry.ScheduleDate <= getDate() +1 and PatientinsuranceProfiles.ActiveFlag = 1 and EligibilityPayorNumber > = 1 ORDER By SCHEDULEDATE I would like to do a few things and can't figure out how: The DOB of is returning a value of Nov 6 1939 12:00AM and I need it to be mmddyyyy. I need to group by TrackingID which can be the same on multiple lines. The data would always be the same. What can I add to the script so when I run it as a SQL it will save as pipe delimited?
For your DOB, this can be used in your SELECT. Note, it will be of type VARCHAR and no longer a datetime. SELECT REPLACE(CONVERT(VARCHAR(10),PatientDemographics.DateofBirth,101),'/','') AS DOB I notice your RTRIM and they could be necessary for your output, but this is just some free knowledge on SQL server and trailing spaces for comparisions: https://support.microsoft.com/en-us/kb/316626 DECLARE #s1 varchar(10) DECLARE #s2 varchar(10) set #s1 = 'nospace' set #s2 = '3spaces ' select len(#s1), len(#s2)
Slow TSQL query with nested selects
I have written a query, but appears to run quite slowly in our live environment. The query contains nested select statements which I believe to slow down execution. Does anyone have any tips of how I could re-write the query to improve the execution speed. DECLARE #StartDate DATETIME DECLARE #EndDate DATETIME SET #StartDate = '20140101' SET #EndDate = '20140101' SELECT a.applicationid, a.ourreference, (SELECT MAX(e.CreateDateTime) FROM tblEmail AS e WHERE( e.ApplicationID = a.ApplicationID) AND (ISNULL(e.StandardEmailID,0) <> 3)) AS 'LastEmail', (SELECT MAX(l.CreateDateTime) FROM tblLetter AS l WHERE l.ApplicationID = a.ApplicationID AND l.ExternalDocumentTypeID IS NULL) AS 'LastInternalLetter', (SELECT MAX(l.CreateDateTime) FROM tblLetter AS l WHERE l.ApplicationID = a.ApplicationID AND l.ExternalDocumentTypeID IS NOT NULL) AS 'LastExternalLetter' INTO #Temp FROM tblapplication AS a WHERE (a.LogDate BETWEEN #StartDate AND #EndDate + '23:59:59') AND (a.BusinessSourceID NOT IN (11, 16)) AND (a.ApplicationStatusID = 100) SELECT * FROM #Temp AS tem WHERE ((LastEmail < LastExternalLetter) AND (LastInternalLetter < LastExternalLetter)) Cheers everyone edit- Sorry I should say what the query is for. I am trying to see if our customers have sent us a letter and we haven't responded to them with a letter/email
select * from ( Select a.applicationId, a.ourreference, max(e.CreateDateTime) LastEmail, max(li.CreateDateTime) LastInternalLetter, max(le.CreateDateTime) LastExternalLetter from tblApplication a left outer join tblEmail e on e.ApplicationID = a.ApplicationID left outer join tblLetter li on li.ApplicationId = a.ApplicationId left outer join tblLetter le on le.ApplicationId = a.ApplicationId WHERE (a.LogDate BETWEEN #StartDate AND #EndDate + '23:59:59') AND (a.BusinessSourceID NOT IN (11, 16)) AND (a.ApplicationStatusID = 100) and (e.StandardEmailID <> 3 or e.StandardEmailId is null) group by a.ApplicationId, a.OurReference )x WHERE ((LastEmail < LastExternalLetter) AND (LastInternalLetter < LastExternalLetter)) This gets rid of the temporary table. Remember, with SQL wherever you have a Table you can substitute a query (in Selects anyway). This should make it a bit more efficient, but you want to look at the Query Plans and see what's holding it up. Cheers -