The following stored procedure takes almost 2 minutes to run which is causing a time out. Both tables do have primary keys and indexes defined. Is there anyway I can improve the process time?
ALTER PROCEDURE [dbo].[dfc_rpt_validation]
-- declare
#region varchar(10) = null,
#source varchar(10) = null
AS BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
select row_number() OVER(ORDER BY l.loan_code) as Id
, l.region AS Region
, l.source AS Source
, l.loan_code_string AS CL_Loan_Code
, l.loan_principal_amt AS CL_Loan_Principal_Amt
, l.loan_amt_due AS CL_Loan_Amt_Due
, l.date_originated AS CL_Origination_Date
, l.StoreNumber AS CL_Store_Number
, v.new_loan_code_string AS FA_Loan_Code
, v.loan_principal_amt AS FA_Loan_Principal_Amt
, v.loan_amt_due AS FA_Loan_Amt_Due
, v.loan_origination_date AS FA_Origination_Date
, (select count(*) from [dbo].[dfc_LoanValidatedRecords] s WHERE s.loan_code_string = l.loan_code_string) AS FA_Times_Loan_Document_Processed
, (CASE WHEN l.rejected_date IS NULL AND l.validated_date IS NULL THEN ''
WHEN v.pdf_legible = 0 THEN 'operational reject' -- operational error
WHEN v.loan_code_valid = 1
AND v.loan_principal_amt_valid = 1
AND v.loan_origination_date_valid = 1
AND v.loan_amt_due_valid = 1
--OR v.pdf_legible = 0 -- operational error
THEN 'validated' ELSE 'rejected' END
) AS [FA_Verification_Status]
-- 100 delivery method failure
-- 200 pdf reject codes
-- 400 borrower info reject codes
-- 600 loan reject codes
, LTRIM(RTRIM (
--(CASE WHEN l.rejected_date IS NULL AND l.validated_date IS NULL THEN ''
--ELSE
(CASE WHEN v.pdf_legible = 0 THEN ' 200'
ELSE
(CASE WHEN v.loan_code_valid = 0 THEN ' 600' ELSE '' END)
+ (CASE WHEN v.loan_principal_amt_valid = 0 THEN ' 610' ELSE '' END)
+ (CASE WHEN v.loan_origination_date_valid = 0 THEN ' 620' ELSE '' END) -- LoanDate
+ (CASE WHEN v.loan_amt_due_valid = 0 THEN ' 625' ELSE '' END)
END) -- operational error
--END)
)) AS FA_Reason
, l.load_file AS load_file
from dfc_LoanRecords AS l
JOIN dfc_LoanValidatedRecords AS v ON v.loan_code_string = l.loan_code_string
WHERE CONVERT (DATE, l.load_date) >= convert(date, dateadd(hh,-8,getdate())) -- handle UTC conversion
AND l.region = #region AND l.source = #source
ORDER BY FA_Verification_Status, FA_Reason
END
Simplest change I can see:
There's no reason I can see for this: CONVERT (DATE, l.load_date).
Just use l.load_date >= convert(date, dateadd(hh,-8,getdate()))
This should enable SQL query optimiser to use any indexes that might exist on load_date. At the moment it can't do so efficiently as you're using a function on the column.
Wouldn't be better if instead of converting the Convert(date, dateadd(hh,-8,getdate()))
in the query itself to avoid that function for every record
DECLARE #Date DATE = CAST(DATEADD(HH,-8,GETDATE()) AS DATE)
WHERE CONVERT (DATE, l.load_date) >= #Date -- handle UTC conversion
AND l.region = #region AND l.source = #source
With this you are going to get a better execution plan instead of converting the value for every single row.
Also if you can apply the ORDER BY at the application layer... please read 7 Things Developers Should Know About SQL Server item 2 please do so, there's no need to use it on the database side unless we have to, it will reduce extra-cost on tempdb.
Related
I'm trying to create a procedure where I can programmatically change the columns in the query based on parameters passed. I'm trying to concatenate the variable to the column field but am unable to. I have been able to achieve this in excel vba by concatenating using " & v_variable & " and it works perfectly. I'm hoping to achieve the same in my stored procedure so I can move my code from excel vba file to the server for many good reasons. One big reason being that copies of this excel file is used by several people and any changes in the code becomes a nightmare to maintain and distribute. Thanks in advance.
I need to concatenate the variable #v_PriceDeltaType to 'Event' (see the case statement in the snippet). Basically I want the program to literally replace the variable value in the query in order to achieve the desired query I have shown below. I need this because the value of the variable can change in order to fetch data from a different column in the view from which the data is coming.
The query example below is a tiny snippet from a massive 5 union query around 60 lines. So I'm hoping the solutions suggested would aim at helping me with concatenating the variables to the query rather than chaning the whole architecture of my query. Otherwise I'll take whatever works.
Below is my procedure snippet:
DECLARE #v_PriceDeltaType varchar(10) = 'PML_Delta',
#v_EventDate Date = '2017-07-18',
#v_WXRegion varchar(10) = 'ALL',
#v_Weekend int = 0,
#HistHEWinDays int = 3,
#v_HistDeltaWin int = 4
SELECT Cast(#v_EventDate as Date) EventDate, Event.Hit, Event.Point,
(CASE
WHEN AVG(Event.#v_PriceDeltaType) < 0 THEN 'OFF'
WHEN AVG(Event.#v_PriceDeltaType) >= 0 THEN 'ON'
ELSE 'Error' END ) EventType
FROM [PowerEvent].[dbo].[v_4_WXL] Event
WHERE WXFDate = #v_EventDate
and LFFEventDate = WXFDate
and LFFRegion = '#v_WXRegion'
and MDDHWeekend = #v_Weekend
GROUP BY Event.Point, Event.Hit
HAVING Count(Event.Hit) > #HistHEWinDays
And Abs(AVG(Event.#v_PriceDeltaType)) > #v_HistDeltaWin
Desired Query: I'd like to have my query looking like this when it runs.
SELECT '2017-07-18' EventDate, Event.Hit, Event.Point,
(CASE
WHEN AVG(Event.PML_Delta) < 0 THEN 'OFF'
WHEN AVG(Event.PML_Delta) >= 0 THEN 'ON'
ELSE 'Error' END ) EventType
FROM [PowerEvent].[dbo].[v_4_WXL] Event
WHERE WXFDate = '2017-07-18'
and LFFEventDate = WXFDate
and LFFRegion = 'ALL' and MDDHWeekend = 0
GROUP BY Event.Point, Event.Hit
HAVING Count(Event.Hit) > 3 And Abs(AVG(Event.PML_Delta)) > 4
Using dynamic sql -- this might take some finessing as I did not test it but hopefully gets you going:
declare #sql nvarchar(max)
DECLARE #v_PriceDeltaType varchar(10) = 'PML_Delta',
#v_EventDate Date = '2017-07-18',
#v_WXRegion varchar(10) = 'ALL',
#v_Weekend int = 0,
#HistHEWinDays int = 3,
#v_HistDeltaWin int = 4
set #sql =
'
SELECT Cast('''+convert(Varchar(10),#v_EventDate,101) +''' as Date) EventDate,
Event.Hit,
Event.Point,
(CASE
WHEN AVG(Event.['+#v_PriceDeltaType+']) < 0 THEN ''OFF''
WHEN AVG(Event.['+#v_PriceDeltaType+']) >= 0 THEN ''ON''
ELSE ''Error'' END ) EventType
FROM [PowerEvent].[dbo].[v_4_WXL] Event
WHERE WXFDate = '''+convert(varchar(10),#v_EventDate,101)+'''
and LFFEventDate = WXFDate
and LFFRegion = '''+#v_WXRegion+'''
and MDDHWeekend = '+convert(varchar(10), #v_Weekend) + '
GROUP BY Event.Point, Event.Hit
HAVING Count(Event.Hit) > '+convert(Varchar(10),#HistHEWinDays) + '
And Abs(AVG(Event.['+#v_PriceDeltaType+'])) > '+convert(varchar(10), #v_HistDeltaWin) +'
'
print #sql
exec(#sql)
I need to improve the performance of a stored procedure that is used by SSRS. When a very narrow set of parameters are passed, the stored procedure completes rather quickly. But when more than a hundred thousand results are returned, the stored procedure takes minutes to run.
For example, if I run this using the date range of 1982 - 2020, it takes 15 minutes to run and returns 180000 records.
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[uspContractFundingbyYear2]') and OBJECTPROPERTY(id, N'IsProcedure') = 1)
drop procedure [dbo].[uspContractFundingbyYear2]
GO
-- =============================================
-- Author: J. Dickens
-- Create date: April 2011
-- Description: This SP generates contract funding records for the selected parameters.
-- Each row should represent a single contract funding record.
-- In many cases, either 0 or 100 is used to designate an option that is not selected. The parameter should have no impact on the query.
-- Otherwise all values are passed to the parameter using the multivalue parameter function.
-- =============================================
CREATE PROCEDURE [dbo].[uspContractFundingbyYear2]
#StartYear datetime
,#EndYear datetime
,#BusinessEntityID nvarchar(max)
,#ContractTypeCode nvarchar(max)
,#ContractStatusCode nvarchar(max)
,#ContractOrgID nvarchar(max)
,#ResearchTypeCode nvarchar(max)
,#ExportControlLevelCode nvarchar(max)
,#ScienceAreaID nvarchar(max)
,#ThrustAreaID nvarchar (max)
,#ContractStartdate datetime
,#ContractEnddate datetime
,#ResearchBusID int
,#MasterContractOnlyFlag bit
,#StateProvinceCode nvarchar(max)
,#CountryID nvarchar(max)
,#FinalYearFlag int
,#CollaborativeDollars int
,#SubcontractsFlag int
,#FundingOrgID nvarchar(max)
,#FundingTypeCode nvarchar(max)
,#FundingStatusCode nvarchar(max)
,#FundingStartdate datetime
,#FundingEnddate datetime
AS
BEGIN
-- SET NOCOUNT ON added to prevent extra result sets from
-- interfering with SELECT statements.
SET NOCOUNT ON;
--- Prepare a table of Year Numbers, for use with Cross Join
DECLARE #Dates TABLE (YearNo INT)
;WITH n(n) AS
(
SELECT YEAR(#StartYear)
UNION ALL
SELECT n+1
FROM n
WHERE n < YEAR(#EndYear)
)
INSERT INTO #Dates(YearNo)
SELECT n
FROM n
ORDER BY n
-- Now find all the contract funding records
select distinct
be.BusinessEntityName
, Q.ScienceArea
, r.ResearchBusID
, c.FormattedBusID
, o.Abbreviation as 'ContractOrg'
, c.StateProvinceCode
, cy.CountryName
, cf.ContractFundingID
, c.ContractTypeCode
, c.ContractID,
, [Thrust] = dbo.ufConcatenateThrustsforResTaskDate (r.ResearchID, NULL, NULL, NULL)
, [PI] = (select STUFF((select distinct(coalesce('; '+P.lastfirst,''))
from ResTaskParticipant rtp
join PersonOrg po on rtp.PersonOrgID = po.PersonOrgID
join Person p on po.PersonID = p.PersonID
where rtp.ResearchID = r.researchid
and rtp.ParticipantTypeCode = 'PI'
and (rtp.enddate > getdate() or rtp.enddate = r.enddate)
for XML path ('')),1,2,'')),
c.ContractStatusCode,
cf.Fundingstatuscode as 'FundingStatus', cf.FundingTypeCode as 'FundingType', cf.Funding,
o2.Abbreviation as 'FundingSourceOrg', cf.StartDate, cf.EndDate,
DATEDIFF(m,cf.StartDate, dateadd(d,2,cf.EndDate)) as 'ContractMonths', --using 2 days here to allow for leap years
[BurnRate] =
case
when DATEDIFF(m,cf.StartDate, dateadd(d,2,cf.EndDate)) = 0 --using 2 days here to allow for leap years
then convert(decimal(2,1), 0)
else
convert(decimal (15,5), convert(decimal(15,0),cf.Funding)/convert(decimal(2,0),(DATEDIFF(m,cf.StartDate, dateadd(d,2,cf.EndDate))))) --using 2 days here to allow for leap years
end
, [IsFirstOfMonth] =
case when cf.startdate = (select FirstDayofMonth from dbo.ufGetFirstLastDayofMonth(cf.StartDate, 0)) then 1 else 0 end
, [IsEndOfMonth] =
case when datepart(day,cf.EndDate) = datepart(day,(select LastDayofMonth from dbo.ufGetFirstLastDayofMonth(cf.EndDate, 0))) then 1 else 0 end
, [MonthsInYear] = Convert(decimal(2,0), (select dbo.ufmonthsincontractforyear (cf.startdate, cf.EndDate, d.YearNo)))
,[YearNo] = d.YearNo
from ContractFunding cf
join Contract c on cf.ContractID = c.ContractID
join Research r on c.ResearchID = r.ResearchID
join BusinessEntity be on r.BusinessEntityID = be.BusinessEntityID
join Organization o on c.OrganizationID = o.OrganizationID --Contract Org
join Country cy on c.CountryID = cy.CountryID
join Organization o2 on cf.SourceOrganizationID = o2.OrganizationID --Funding Org
left outer join TaskFunding tf on cf.ContractFundingID = tf.ContractFundingID
--Get the range of years for each Contract Funding row
cross join #Dates d
--get Science Area
cross apply (select [ScienceArea] = dbo.ufConcatenateScienceAreasforResTaskDate (r.ResearchID, NULL, NULL, NULL)) as Q
where
-- required parameters for running report are Start and End Years
cf.StartDate <= #EndYear and cf.EndDate >= #StartYear
-- now all the bells and whistles
and r.BusinessEntityID in (select val from [dbo].[ufStringToTable] (#BusinessEntityID,',',1))
and c.ContractTypeCode in (select val from [dbo].[ufStringToTable] (#ContractTypeCode,',',1))
and c.ContractStatusCode in (select val from [dbo].[ufStringToTable] (#ContractStatusCode,',',1))
and c.OrganizationID in (select val from dbo.ufStringToTable (#ContractOrgID,',',1))
and (#ResearchTypeCode = '0' or (r.ResearchTypeCode in (select val from dbo.ufStringToTable (#ResearchTypeCode,',',1))))
and (#ExportControlLevelCode = '100' or c.ExportControlLevelCode = #ExportControlLevelCode)
-- For Science Area Funding, of the set of Contract Funding records returned, select those that match the given Science Area
and (#ScienceAreaID = '0' or (cf.ScienceAreaID in (select val from dbo.ufStringToTable (#ScienceAreaID,',',1))))
-- For Thrust Area Funding, of the set of Contract Funding records returned, select those that match the given Thrust Area
and (#ThrustAreaID = '0' or (tf.ThrustAreaID in (select val from dbo.ufStringToTable (#ThrustAreaID,',',1))))
-- Find Contracts within given "Active" dates
and (
(#ContractStartdate is null and #ContractEnddate is null)
OR
(c.enddate > #ContractStartdate and c.StartDate <=#ContractEnddate)
or
(#ContractStartdate is null and c.StartDate <=#ContractEnddate)
or
(c.EndDate > #ContractStartdate and #ContractEnddate is null)
)
and (#ResearchBusID = '' or r.ResearchBusID = #ResearchBusID)
and (#MasterContractOnlyFlag = 0 or (#MasterContractOnlyFlag = 1 and c.MasterContractFlag = 1))
and (#StateProvinceCode = '0' or (c.StateProvinceCode in (select val from dbo.ufStringToTable (#StateProvinceCode,',',1))))
and c.CountryID in (select val from dbo.ufStringToTable (#CountryID,',',1)) --Not all contracts have a country assignment
and (#FinalYearFlag = 100
or
(#FinalYearFlag = 0 and (dbo.ufContractIsInFinalYear(c.contractid,getdate()) = 0))
or
(#FinalYearFlag = 1 and (dbo.ufContractIsInFinalYear(c.contractid,GETDATE()) = 1))
)
and (#CollaborativeDollars = 100
or
(#CollaborativeDollars = 0 and
not exists
(select * from ContractFunding cf2 where cf2.FundingTypeCode='Collaborative' and cf2.ContractID=c.ContractID)
)
or
(#CollaborativeDollars = 1 and
exists
(select * from ContractFunding cf2 where cf2.FundingTypeCode='Collaborative' and cf2.ContractID=c.ContractID)
)
)
and (#SubcontractsFlag = 100
or
(#SubcontractsFlag = 0 and c.SubContractFlag = 0)
or
(#SubcontractsFlag = 1 and c.SubContractFlag = 1)
)
and (cf.SourceOrganizationID in (select val from dbo.ufStringToTable (#FundingOrgID,',',1)))
and (cf.FundingTypeCode in (select val from dbo.ufStringToTable (#FundingTypeCode,',',1)))
and (cf.FundingStatusCode in (select val from dbo.ufStringToTable (#FundingStatusCode,',',1)))
and (
(#FundingStartdate is null and #FundingEnddate is null)
OR
(c.enddate > #FundingStartdate and c.StartDate <=#FundingEnddate)
or
(#FundingStartdate is null and c.StartDate <=#FundingEnddate)
or
(c.EndDate > #FundingStartdate and #FundingEnddate is null)
)
End
GO
Query which should be stored as variable in "Execute SQL Task":
Use [Reporting]
Go
DECLARE
#current_month DATETIME,
#current_year DATETIME,
#current_year_final AS INT,
#previous_period_final VARCHAR(2),
#test_period AS VARCHAR (2),
#previous_period_final_2 VARCHAR(2)
SET #current_month = DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()),0)
SET #current_year = DATEADD(YEAR,DATEDIFF(YEAR,0,GETDATE()),0)
SET #current_year_final = CASE WHEN LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),4),2) = '01' THEN LEFT(CONVERT(VARCHAR,#current_year,112),4)-1 ELSE LEFT(CONVERT(VARCHAR,#current_year,112),4) END
SET #previous_period_final = CASE
WHEN CAST(LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),4),2) AS INT) - 1 BETWEEN 10 AND 11 THEN CAST(CAST(LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),4),2) AS INT) - 1 AS VARCHAR) -- Type Varchar
WHEN CAST(LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),3),1) AS INT) - 1 BETWEEN 1 AND 8 THEN '0' + CAST(CAST(LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),3),1) AS INT) - 1 AS VARCHAR)
WHEN CAST(LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),4),2) AS INT) - 1 = 9 THEN '09'
WHEN LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),4),2) = '01' THEN '12'
ELSE 'Invalid formula' END
SET #previous_period_final_2 = CAST(LEFT(RIGHT(CONVERT(VARCHAR, GETDATE(),112),4),2) AS INT) - 1
-- ### Returns:
-- 1 = 'identical' = row numbers match
-- 0 = 'mis-matched' = row numbers do not match
select sum(rows_identical) as rows from
(
select CAST(CAST(case when count_rows_raw = count_rows_facts then 1 else 0 end as bit)as int) as rows_identical
--,SQL_VARIANT_PROPERTY(CAST(CAST(case when count_rows_raw = count_rows_facts then 1 else 0 end as bit)as int),'BaseType') -- ### EXCELLENT WAY TO RETRIEVE DATATYPE ###
from
(
select
(
select SUM(#rows_facts) as #rows_facts from
(
select COUNT(ID) as #rows_facts, 'finalized_entries_facts_table' as type from facts_reporting
where YearMonthID in (select YearMonthID from dim_year_month as yyMM
where yyMM.YearMonth = CAST(#current_year_final AS Varchar)+'_'+CAST(#previous_period_final AS Varchar))
and SourceID IN (select SourceID from dbo.dim_source where Source = 'Unlocks')
union
select COUNT(ID) as #rows_facts, 'missing_entries_facts_table' as type from missing_ids_Unlocks_raw
where YearMonthID in (select YearMonthID from dim_year_month as yyMM
where yyMM.YearMonth = CAST(#current_year_final AS Varchar)+'_'+CAST(#previous_period_final AS Varchar))
and SourceID IN (select SourceID from dbo.dim_source where Source = 'Unlocks')
) as rows
) as count_rows_facts,
(
SELECT count(*)as #rows_raw from UnlocksRawCSV_table as raw
Where Year_Month_inserted = CAST(#current_year_final AS Varchar) + '_' + #previous_period_final
) as count_rows_raw
)
as row_checks
)
as count_check
--where rows_identical <> 0
Variable definition and Result Set mapping in SSIS:
In the Execute SQL Task I have selected "Result Set = Single row". I have also tried "None". I have put a post-execute Breakpoint on the Execute SQL Task and get this:
== Why am I getting a 0 as value in SSIS while I am getting a 1 if I execute this query (see above) in SQL Server directly?
The precedence constraint in the subsequent task look like this:
EDIT 1: Changing this expression to #RowCheck == 0 does not change anything as the task still fails on execution with the same error:
Error: No result rowset is associated with the execution of this query
EDIT: 2: Changing the Value in the Precedence Constraint Editor from "Success" to "Failure" works but I don't understand why the task itself fails and why it generates the above mentioned error message? However, despite proceeding with the package the value displayed for variable RowCheck does not make any sense as it is always zero, regardless of that the Query returns...
EDIT 3: Screen of General Tab for Execute SQL Statement (I have also tried with "Single Row" and above mentioned Result Set Mapping:
I've looked around and found various approaches to this problem, but none that worked in my specific situation. I wrote a stored procedure which I'm using for an SSRS report which accommodates for optional parameters (in SSRS, I'm specifying a list of available parameters, along with an "All" option where the value is set to "=Nothing"). This works for accommodating for multiple optional parameters when, if nothing is selected, all records are shown... except for those with null ProjectID values.
I'd like to be able to run the stored procedure and specify "Null" for the #Project parameter and be shown those values with null ProjectID fields, and ideally, add a "None" option to my SSRS report for this parameter, which would also show those values.
I'm not quite sure how to modify the SP to achieve this:
ALTER PROCEDURE [dbo].[TasksByStatus]
#Status AS Integer = NULL,
#Project AS Integer = NULL
AS
BEGIN
SELECT Task, CONVERT(VARCHAR, StartDate, 101) AS StartDate,
(CASE WHEN CompleteDate IS NULL THEN 'Not complete yet'
ELSE CONVERT(VARCHAR, CompleteDate, 101) END) AS CompleteDate,
(CASE WHEN Notes IS NULL THEN 'No notes provided' ELSE Notes END) AS Notes,
ProjectName, StatusName
FROM Tasks
INNER JOIN Status ON Tasks.StatusID = Status.ID
LEFT JOIN Projects ON Tasks.ProjectID = Projects.ID
AND Projects.ID IS NULL
WHERE Status.ID = ISNULL(#Status, Status.ID)
AND Projects.ID = ISNULL(#Project, Projects.ID)
ORDER BY StartDate, StatusName
END
Results of query without specifying parameters:
I intent, when specifying NULL for #Project to see only that one record with a NULL ProjectID value.
Edit to further clarify
To OP, please let us know what the exact results should be for each row in given table. Also, when you mention 'None', how would you like to pass that to the stored procedure? (The #Project variable is defined as integer)
Parameter Projects.ID In Result
-----------------------------------------
1 1 Yes
1 2 No
1 NULL No
'None' 1 No
'None' 2 No
'None' NULL Yes
NULL 1 Yes
NULL 2 Yes
NULL NULL Yes
If you want to LEFT JOIN on Products, then you need to include that clause in ON not WHERE. Putting it in WHERE makes it an INNER JOIN.
ALTER PROCEDURE [dbo].[TasksByStatus]
#Status INT = NULL,
#Project INT = NULL
AS
BEGIN
SET NOCOUNT ON;
SELECT
Task,
CONVERT(VARCHAR, StartDate, 101) AS StartDate,
(CASE WHEN CompleteDate IS NULL THEN 'Not complete yet'
ELSE CONVERT(VARCHAR, CompleteDate, 101) END) AS CompleteDate,
(CASE WHEN Notes IS NULL THEN 'No notes provided' ELSE Notes END) AS Notes,
ProjectName, StatusName
FROM dbo.Tasks
INNER JOIN dbo.Status ON Tasks.StatusID = Status.ID
LEFT JOIN dbo.Projects ON Tasks.ProjectID = Projects.ID
WHERE Status.ID = COALESCE(#Status, Status.ID)
AND COALESCE(Projects.ID, -1) = COALESCE(#Project, Projects.ID, -1)
ORDER BY StartDate, StatusName;
END
GO
This kind of query is the shortcut for disaster. Remember, SQL must compile a query plan that work for any value of the parameters. Therefore it will be pretty much forced to do a table scan on both Status and Projects tables even when #Project and/or #Status were specified! Erland Sommarskog covers this topic in detail at Dynamic Search Conditions in T-SQL
Separate this into 3 different queries:
if (#Status is null and #Project is null)
select ...;
else if (#status is null)
select ... where ProjectID = #Project;
else if (#project is null)
select ... where StatusID = #status;
else
select ... where StatusID = #status and ProjectID = #Project;
How to subtract two time values in SQL Server 2008. I am using time variables in a stored procedure.
Please help.
You can use DATEDIFF():
SELECT DATEDIFF(Day, startDate, endDate)
FROM table
SELECT DATEDIFF(Second, date, GETDATE())
FROM table
DECLARE #END TIME = '16:00:00.0000000' ,
#START TIME = '01:00:00.0000000'
SELECT convert(TIME,dateadd(ms,DateDiff(ss, #START, #END )*1000,0),114)
following expression works for me
declare #starttime Time, #endtime Time
set #starttime='18:45'
set #endtime='22:45'
select DATEDIFF(HH,#starttime, #endtime)
output: 4
Even You are using offset value or normal dates this code will give you appropriate answers.
BEGIN TRY
DECLARE #OffSetVal1 VARCHAR(39) = '2019-12-02 09:15:29 +14:00'
, #OffSetVal2 VARCHAR(39) = '2019-12-02 09:15:29 +12:30'
, #minutes INT = 0
, #OffSetDiff VARCHAR(19) = ''
, #HourDiff INT = 0
SET #HourDiff = DATEDIFF(HOUR,#OffSetVal1,#OffSetVal2) -- To Check digits of hours.
SET #minutes = DATEDIFF(MINUTE,#OffSetVal1,#OffSetVal2) -- To Convert minutes to hours.
SET #OffSetDiff = #minutes / 60 + (#minutes % 60) / 100.0 -- To Check '+' Or '-' And To Get Value.
SELECT CASE WHEN CAST(#OffSetDiff AS FLOAT) <= 0
THEN (CASE WHEN #HourDiff < 10
THEN FORMAT(CAST(#OffSetDiff AS FLOAT),'0#.00')
ELSE FORMAT(CAST(#OffSetDiff AS FLOAT),'0#.00')
END)
ELSE (CASE WHEN #HourDiff < 10
THEN '+'+FORMAT(CAST(#OffSetDiff AS FLOAT),'0#.00')
ELSE '+'+FORMAT(CAST(#OffSetDiff AS FLOAT),'0#.00')
END)
END
END TRY
BEGIN CATCH
PRINT N'It seems you provided an invalid DateTimeOffSet Parameter. '
END CATCH
ANS :- +01.30 (# The offset differences with hour and minute and if you don't want that '+' simply remove from code & then run the code)