SQL 2008 - Insert into table if date does not already exist - sql-server-2008

Hi how can I make the following script to insert work.
First to check if table Exists if yes insert into table only, and I only want to insert into the table if the date range is not already in the table. Otherwise do select into table.
DECLARE #date1 datetime
DECLARE #date2 datetime
DECLARE #dailyEnd1 varchar(12)
DECLARE #dailyEnd2 varchar(12)
DECLARE #column varchar(100)
DECLARE #Script varchar(8000)
SET #date1 = '09 jan 2012'
SET #date2 = '15 jan 2012'
SET #dailyEnd1 = #date1
SET #dailyEnd2 = #date2
IF OBJECT_ID('tempdb..#table1') is not null
BEGIN
IF NOT EXIST (SELECT MinDate, MaxDate FROM #table1
WHERE MinDate = '02 Jan 2012' AND MaxDate = '08 jan 2012'
GROUP BY MinDate, MaxDate)
BEGIN
INSERT INTO #table1 (MinDate, MaxDate, [Week], OutletID, OutletName, Transactions, Spend)
SELECT min(dailyEnd-1), max(dailyEnd-1),
convert(varchar(12),Min(dailyEnd-1), 104)+'-'+convert(varchar(12),MAX(dailyEnd-1),104),
OutletID, OutletName,
sum(Transactions), sum(Sales)
FROM #table2 (NOLOCK)
WHERE dailyEnd-1 >= #dailyEnd1
AND dailyEND-1 <= #dailyEnd2
GROUP BY OutletID, OutletName
END
END
ELSE
BEGIN
SELECT min(dailyEnd-1) as MinDate, max(dailyEnd-1) as MaxDate,
convert(varchar(12),Min(dailyEnd-1), 104)+'-'+convert(varchar(12),MAX(dailyEnd-1),104) as [Week], OutletID, OutletName, sum(Transactions) as Transactions, sum(Sales) as Spend
INTO #table1
FROM #table2 (NOLOCK)
WHERE dailyEnd-1 >= #dailyEnd1
AND dailyEND-1 <= #dailyEnd2
GROUP BY OutletID, OutletName
END
Thanks

Move your NOT EXISTS clause down in the WHERE after your INSERT.
Meaning, only insert where NOT EXISTS for the date range.

Related

How to search sequence of Date Ranges in SQL

When trying to check date ranges it does not return values. Here st_date and end_date for usr_id = 1 is sequence so it should return only usr_id = 1 values and should not return usr_id = 3 since it is not sequence . If the date range is not in sequence, it should not return any value.
CREATE TABLE #temp(st_date DATE,end_date DATE,usr_id INT)
INSERT #temp
VALUES ('2007-03-01 ','2015-01-31 ',1),
('2015-02-01 ','2017-04-01 ',1),
('2007-03-01 ','2014-01-31 ',2),
('2007-03-01 ','2015-01-31 ',3),
('2015-03-02 ','2017-04-01 ',3)
DECLARE #st_dt DATE = '2009-02-01 00:00:00',#end_dt DATE = '2017-01-01 00:00:00'
SELECT * FROM #temp WHERE #st_dt BETWEEN st_date AND end_date
AND #end_dt BETWEEN st_date AND end_date
DROP TABLE #temp
SELECT *
FROM #temp t
INNER JOIN #temp t2 ON t.usr_id = t2.usr_id AND t.end_date = DATEADD(dd, -1, t2.st_date)
WHERE #st_dt BETWEEN t.st_date AND t.end_date
AND #end_dt BETWEEN t2.st_date AND t2.end_date

Rewrite Stored Procedure

I have the next stored procedure which inserts values into 2 tables. To the 2nd table I insert id's of 2 last inserts from 1st table
However, I would like to rewrite it with one query instead of using temp table and while.
CREATE PROCEDURE CurrencyExhange
AS
DECLARE #TmpTable Table
(
ID int IDENTITY(1,1) NOT NULL PRIMARY KEY,
BillID int,
Amount decimal,
Rate decimal,
Date date
)
INSERT INTO #TmpTable
SELECT T.[BillID]
,[Amount]
,CR.Rate
,CR.Date
FROM [FinanceLabkovich].[dbo].[Transactions] T
JOIN [FinanceLabkovich].[dbo].Bills B ON B.BillID = T.BillID
JOIN [FinanceLabkovich].[dbo].Currencies C ON C.CurrencyID=B.CurrencyID
JOIN [FinanceLabkovich].[dbo].CurrencyRates CR ON CR.CurrencyRateID=FinanceLabkovich.dbo.GetRate(T.Date)
WHERE LOWER(C.Name)='usd' AND T.Income=1
ORDER BY T.Date
DECLARE #ToBillID int = (SELECT BillID FROM [FinanceLabkovich].[dbo].Bills B WHERE B.Name='Purse')
DECLARE #i int = (SELECT MIN(Id) FROM #TmpTable)
DECLARE #maxId int = (SELECT MAX(Id) FROM #TmpTable)
DECLARE #TransactionID int, #ToTransactionID int, #Amount decimal
DECLARE #date date
WHILE (#i<=#maxId)
BEGIN
SET #date = (SELECT Date FROM #TmpTable WHERE ID=#i)
SET #Amount = (SELECT AmountUSD FROM [FinanceLabkovich].[dbo].Cashflow WHERE Date=#date)
IF #Amount > 0
BEGIN
INSERT INTO [FinanceLabkovich].[dbo].[Transactions] (Name,BillID,ToBillID,Amount,Date,Income)
SELECT "Name"='Currency exhange'
,BillID
,#ToBillID
,#Amount
,T.Date
,"Income"=0
FROM #TmpTable T
WHERE ID=#i
SET #TransactionID = ##IDENTITY
INSERT INTO [FinanceLabkovich].[dbo].[Transactions] (Name,BillID,ToBillID,Amount,Date,Income)
SELECT "Name"='Currency exhange'
,#ToBillID
,BillID
,#Amount*Rate AS Total
,Date
,"Income"=1
FROM #TmpTable WHERE ID=#i
SET #ToTransactionID = ##IDENTITY
INSERT INTO [FinanceLabkovich].[dbo].[Transfers]
SELECT #TransactionID, #ToTransactionID
END
SET #i += 1
END
Any help appreciated.

List dates between two date range

I have table 1 with 3 columns id, startdate and enddate. With order id being the primary key how do I list the dates between the date range Startdate and Enddate?
What I have:
id Startdate EndDate
1 2/11/2014 2/13/2014
2 2/15/2014 2/17/2014
What I need:
id Date
1 2/11/2014
1 2/12/2014
1 2/13/2014
2 2/15/2014
2 2/16/2014
2 2/17/2014
How do I do this?
Use recursive CTE:
WITH tmp AS (
SELECT id, StartDate AS [Date], EndDate
FROM MyTable
UNION ALL
SELECT tmp.id, DATEADD(DAY,1,tmp.[Date]), tmp.EndDate
FROM tmp
WHERE tmp.[Date] < tmp.EndDate
)
SELECT tmp.ID, tmp.[Date]
FROM tmp
ORDER BY tmp.id, tmp.[Date]
OPTION (MAXRECURSION 0) -- For long intervals
If you have to use cursor/loop, most times you are doing it wrong.
If you do a one-off setup of an auxiliary calendar table as shown at Why should I consider using an auxiliary calendar table?, possibly omitting a lot of the columns if you don't need them, like this:
CREATE TABLE dbo.Calendar
(
dt SMALLDATETIME NOT NULL
PRIMARY KEY CLUSTERED,
Y SMALLINT,
M TINYINT,
D TINYINT
)
GO
SET NOCOUNT ON
DECLARE #dt SMALLDATETIME
SET #dt = '20000101'
WHILE #dt < '20300101'
BEGIN
INSERT dbo.Calendar(dt) SELECT #dt
SET #dt = #dt + 1
END;
UPDATE dbo.Calendar SET
Y = YEAR(dt),
M = MONTH(dt),
D = DAY(dt);
(You may well not need the Y, M, D columns at all, but I left those in to show that more data can be stored for fast access - the article I linked to shows how that could be used.)
Then if your table is named "so", your code would simply be
SELECT A.id, C.dt
FROM so AS A
JOIN Calendar AS C
ON C.dt >= A.StartDate AND C.dt<= A.EndDate
An advantage of using an auxiliary table like that is that your queries can be faster: the work done in setting one up is a one-time cost which doesn't happen during usage..
Instead of using CTE (to over come recursive and performance when date range is large) below query can be used to get the list of dates between two date range.
DECLARE #StartDateSTR AS VARCHAR(32); DECLARE #EndDateSTR AS
VARCHAR(32); DECLARE #EndDate AS DATE; DECLARE #StartDate AS DATE;
SET #StartDateSTR = '01/01/1990'; SET #EndDateSTR = '03/31/2025'; SET
#StartDate = CAST(#StartDateSTR AS date); SET #EndDate =
cast(#EndDateSTR AS date); SELECT
DATEADD(DAY, n1.rn - 1, #StartDate) AS dt FROM (SELECT rn=Row_number() OVER( ORDER BY (SELECT NULL)) FROM sys.objects a
CROSS JOIN sys.objects b CROSS JOIN sys.objects c CROSS JOIN
sys.objects d) as n1 WHERE n1.[rn] <= Datediff(dd, #StartDate,
#EndDate)+1;

mysql query uses every row of another query

I have searched a lot, but cannot find a helpful answer:
i want to have a list of totals from a period the user defines by giving me a start and end date. The totals should every time being from the start date to beginning with the start date and add every row 1 day. so the last row gives the totals from start to end date.
example: - given period = start 2013-01-01 , end = 2013-01-31
total day 1 = 100
total day 2 = 0 (not listed in my totalsperday query, but should have a row in my final query)
total day 3 = 140
total day 4 = 20
...
final table should look like:
end day 1: 100
end day 2: 100
end day 3: 240
end day 4: 260
...
so i have a query who calculates all days:
SELECT '2013-01-01' as startdate, w.endDate
FROM
(
SELECT date('2013-01-01' + INTERVAL u.i*100 + v.i*10 + w.i DAY) AS endDate
FROM sysints AS u
JOIN sysints AS v
JOIN sysints AS w
WHERE ( u.i*100 + v.i*10 + w.i ) <=
(
SELECT DATEDIFF( '2013-01-31','2013-01-01') as ddff
)
) w
ORDER BY w.endDate ASC
and i have a query who calculates the totals per day
SELECT p.selldate, SUM(p.price) as totalPerDay
FROM products p
WHERE '2013-01-01' >= p.selldate <= '2013-01-31'
GROUP BY p.selldate
ORDER BY p.selldate ASC
now combining these two to get my final result is hard.
basically what the final query should look like is:
- make the sum of sumperday from day 1 to day 1
- make the sum of sumperday from day 1 to day 2
- make the sum of sumperday from day 1 to day 3
...
any help?
thx.
this is a simplified example of my final query.
Below is the sample. The idea is to obtain a initial data set ordered by date and having aggregate totals, implicit date range records. Then using the cursor you can pass through each row to get the final total column (amountCalc column in the sample) just by summarize the previous records - will work because you already have the columns ordered by date.
The procedure can have other input/ output parameters. Instead of getting info from table you can get data from one view, where the view can be already order by date asc. Is just a sample so can be customized as needed.
Good luck.
-- drop table `Balance`;
CREATE TABLE `Balance` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL,
`account` varchar(30) NOT NULL,
`amount` DECIMAL(10,2) NOT NULL,
PRIMARY KEY (`id`)
);
INSERT INTO `Balance` (`date`, `account`, `amount`) VALUES
('2013-01-02', 'T355176', 8700),
('2013-01-03', 'T355176', 8900),
('2013-01-04', 'T355215', 33308),
('2013-01-03', 'T355215', 116581),
('2013-01-06', 'T812022', 275000),
('2013-01-02', 'T812063', 136500),
('2013-01-05', 'T812063', 11682),
('2013-01-06', 'T812064', 615100),
('2013-01-03', 'T812064', 25000),
('2013-01-02', 'T812085', 82500);
SELECT * FROM Balance WHERE date >= '2013-01-01' AND date <= '2013-01-06' ORDER BY date ASC;
CALL sp_getTotals('2013-01-01', '2013-01-06');
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`#`%` PROCEDURE `sp_getTotals`(IN startDate DATE, IN endDate DATE)
BEGIN
DECLARE dt DATE;
DECLARE amt DECIMAL(10,2);
DECLARE amtCalcPart DECIMAL(10,2);
DECLARE done INT DEFAULT 0;
DECLARE dtStart DATE;
DECLARE dtEnd DATE;
DECLARE cur1 CURSOR FOR SELECT date, amount FROM `TempMB`;
DECLARE cur2 CURSOR FOR SELECT startDate, endDate;
DECLARE CONTINUE HANDLER FOR NOT FOUND SET done = 1;
DROP TEMPORARY TABLE IF EXISTS `TempMB`;
CREATE TEMPORARY TABLE IF NOT EXISTS `TempMB` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`date` DATE NOT NULL,
`amount` DECIMAL(10,2) NULL DEFAULT 0.00,
`amountCalc` DECIMAL(10,2) NULL DEFAULT 0.00,
PRIMARY KEY (`id`)
);
SET dtStart = DATE(startDate);
SET dtEnd = DATE(endDate);
WHILE dtStart <= dtEnd DO
INSERT INTO `TempMB` (`date`) SELECT dtStart;
SET dtStart = DATE_ADD(dtStart, INTERVAL 1 DAY);
END WHILE;
SELECT * FROM TempMB;
-- Fill temp table with info needed
UPDATE `TempMB` t
INNER JOIN
(
SELECT date, SUM(amount) AS amount
FROM Balance
WHERE
date >= startDate AND date <= endDate
GROUP BY date
ORDER BY date ASC
) b ON b.date = t.date
SET
t.amount = b.amount;
/*INSERT INTO `TempMB` (`date`, `amount`)
SELECT date, SUM(amount) AS amount
FROM Balance
WHERE
date >= startDate AND date <= endDate
GROUP BY date
ORDER BY date ASC;
*/
SET amtCalcPart = 0.00;
-- Initialise cursor
OPEN cur1;
-- USE BEGIN-END handler for cursor-control within own BEGIN-END block
BEGIN
DECLARE EXIT HANDLER FOR NOT FOUND BEGIN END;
-- Loop cursor throu temp records
LOOP
-- Get next value
FETCH cur1 INTO dt, amt;
-- Calculate amountCalc
SET amtCalcPart = (SELECT SUM(amount) as amt FROM `TempMB` WHERE Date <= dt);
UPDATE `TempMB` SET amountCalc = amtCalcPart WHERE date = dt;
END LOOP;
END;
-- Release cursor
CLOSE cur1;
SELECT * FROM TempMB;
END

Better Min/Max Function for Dates in T-SQL

I created the following function to determine the MAX date between two dates. It takes roughly from 00.030 to 00.050 seconds to run one of the SELECT statements in the function's comment.
Is there a better performing and cleaner way?
/* Returns the greater of two dates.
SELECT dbo.fnMaxDate(NULL , NULL)
SELECT dbo.fnMaxDate('1/1/2011', NULL)
SELECT dbo.fnMaxDate(NULL , '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/2/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/2/2011')
*/
ALTER FUNCTION dbo.fnMaxDate
(
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS datetime
AS
BEGIN
DECLARE #Result DATETIME
IF #Date1 IS NULL AND #Date2 IS NULL
SET #Result = NULL;
ELSE IF #Date1 IS NULL
SET #Result = #Date2
ELSE IF #Date2 IS NULL
SET #Result = #Date1
ELSE
IF #Date1 >= #Date2
SET #Result = #Date1
ELSE
SET #Result = #Date2
RETURN #Result
END
ALTER FUNCTION dbo.fnMaxDate
(
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS datetime
AS
BEGIN
RETURN
CASE
WHEN ISNULL(#Date1, #Date2) > ISNULL(#Date2, #Date1)
THEN ISNULL(#Date1, #Date2)
ELSE ISNULL(#Date2, #Date1)
END
END
I found that a case structure runs about three times faster than a function call.
declare #d table(d1 date, d2 date);
insert into #d values(null,null)
, ('2/19/2012',null)
, (null,'2/19/2012')
, ('2/1/2012','2/15/2012')
, ('2/1/2012','1/15/2012');
declare #md date
, #i int=1
, #ts datetime2
, #ms1 int
, #ms2 int;
-- function
select #ts=GETDATE();
while #i<10000 begin select #md=dbo.fnMaxDate(d1,d2) from #d; set #i+=1; end
select #ms1=DATEDIFF(ms,#ts,GETDATE());
-- recommended case structure
set #i=1;
select #ts=GETDATE();
while #i<10000 begin select #md=case when ISNULL(d1,d2)<ISNULL(d2,d1) then ISNULL(d2,d1) else ISNULL(d1,d2) end from #d; set #i+=1; end
select #ms2=DATEDIFF(ms,#ts,GETDATE());
select [Function Run Time (ms)]=#ms1, [Case Run Time (ms)]=#ms2
go
Result:
Function Run Time (ms) Case Run Time (ms)
---------------------- ------------------
940 296
/* Returns the greater of two dates.
SELECT dbo.fnMaxDate(NULL , NULL)
SELECT dbo.fnMaxDate('1/1/2011', NULL)
SELECT dbo.fnMaxDate(NULL , '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/2/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/2/2011')
*/
ALTER FUNCTION dbo.fnMaxDate
(
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS datetime
AS
BEGIN
DECLARE #Result datetime
SELECT TOP 1 #Result = T.DateValue
FROM
(
SELECT #Date1 DateValue
UNION ALL
SELECT #Date2 DateValue
) T
ORDER BY
T.DateValue DESC
RETURN #Result
END
I know this is an old question, and already answered, but seeing as there was already a test script I couldn't resist having a go :)
I've created a scalar function that outperforms all the other function tests here, and a table valued function that is even faster than the scalar UDF.
Comparable Result (to AMissico's test)
TVF = 0.022253313291
SVF = 0.04627526226
The Functions
/* Returns the greater of two dates.
SELECT dbo.fnMaxDate(NULL , NULL)
SELECT dbo.fnMaxDate('1/1/2011', NULL)
SELECT dbo.fnMaxDate(NULL , '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/2/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/2/2011')
*/
CREATE FUNCTION dbo.svfMaxDate
(
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS datetime
AS
BEGIN
RETURN coalesce(dateadd(dd, ((datediff(dd, 0, #Date1) + datediff(dd, 0, #Date2)) + abs(datediff(dd, 0, #Date1) - datediff(dd, 0, #Date2))) / 2, 0), #Date1, #Date2)
END
GO
CREATE FUNCTION dbo.tvfMaxDate
(
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS TABLE WITH SCHEMABINDING AS
RETURN SELECT [MaxDate] = coalesce(dateadd(dd, ((datediff(dd, 0, #Date1) + datediff(dd, 0, #Date2)) + abs(datediff(dd, 0, #Date1) - datediff(dd, 0, #Date2))) / 2, 0), #Date1, #Date2)
;
GO
I also used AMissico's simple test script to test this, but only bothered to test my version of the functions and the CASE statement to be used as a reference point/baseline:
Results of Test
Case(ms) svfMaxDate tvfMaxDate
0.01343000 0.03907000 0.01837000
Normalise Test Results to AMissico's Baseline
Baseline Case(ms) / This Test Case(ms) = Normalisation Factor
0.01616 / 0.01334000 = 1.21139430
svfMaxDate * Normalisation Factor= Comparable Result
0.03820000 * 1.21139430 = 0.04627526226
tvfMaxDate * Normalisation Factor= Comparable Result
0.01837 * 1.21139430 = 0.022253313291
Test Script
declare #d table(d1 date, d2 date);
insert into #d values(null,null)
, ('2/19/2012',null)
, (null,'2/19/2012')
, ('2/1/2012','2/15/2012')
, ('2/1/2012','1/15/2012');
declare #md date
, #i int=1
, #ts datetime2
, #ms0 int
, #ms1 int
, #ms2 int
;
-- case structure
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=case when ISNULL(d1,d2)<ISNULL(d2,d1) then ISNULL(d2,d1) else ISNULL(d1,d2) end from #d; set #i+=1; end
select #ms0=DATEDIFF(ms,#ts,GETDATE());
-- svfMaxDate, Arithmetic
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=dbo.svfMaxDate(d1,d2) from #d; set #i+=1; end
select #ms1=DATEDIFF(ms,#ts,GETDATE());
-- tvfMaxDate, Arithmetic in TVF with CROSS APPLY
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md = tf.MaxDate from #d cross apply dbo.tvfMaxDate(d1,d2) as tf; set #i+=1; end
select #ms2=DATEDIFF(ms,#ts,GETDATE());
select [Case(ms)]=#ms0/100000.0, fnMaxDate=#ms1/100000.0, tvfMaxDate=#ms2/100000.0
go
The TVF credit goes to Jeff Moden, the following link was used as a reference for building it: How to Make Scalar UDFs Run Faster (SQL Spackle)
Based on my simple performance testing, I am going with a slightly modified version of my original function (see below).
IS NULL CASE IS NOT NULL UNION
Case(ms) Empty Func fnMaxDate1 fnMaxDate2 fnMaxDate3 fnMaxDate4
0.01616 0.0446 0.0518 0.04934 0.05036 0.06177
The fastest function method is the CASE statement, but only by approx. 0.003ms The slowest function is the one that uses SELECT UNION by "Pittsburgh DBA". I changed the order of my function to test for the most common result first, which would test both arguments as IS NOT NULL. This change in logic place the performance on par with the CASE function.
Therefore, I am giving up the 0.001ms performance for clarity of the IS NOT NULL function (see below).
Using the following script:
declare #d table(d1 date, d2 date);
insert into #d values(null,null)
, ('2/19/2012',null)
, (null,'2/19/2012')
, ('2/1/2012','2/15/2012')
, ('2/1/2012','1/15/2012');
declare #md date
, #i int=1
, #ts datetime2
, #ms0 int
, #ms1 int
, #ms3 int
, #ms2 int
, #ms4 int
, #ms5 int
;
-- case structure
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=case when ISNULL(d1,d2)<ISNULL(d2,d1) then ISNULL(d2,d1) else ISNULL(d1,d2) end from #d; set #i+=1; end
select #ms0=DATEDIFF(ms,#ts,GETDATE());
-- fnMaxDate1, IF IS NULL
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=dbo.fnMaxDate1(d1,d2) from #d; set #i+=1; end
select #ms1=DATEDIFF(ms,#ts,GETDATE());
-- fnMaxDate2, CASE
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=dbo.fnMaxDate2(d1,d2) from #d; set #i+=1; end
select #ms2=DATEDIFF(ms,#ts,GETDATE());
-- fnMaxDate3, IF IS NOT NULL
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=dbo.fnMaxDate3(d1,d2) from #d; set #i+=1; end
select #ms3=DATEDIFF(ms,#ts,GETDATE());
-- fnMaxDate4, SELECT UNION
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=dbo.fnMaxDate4(d1,d2) from #d; set #i+=1; end
select #ms4=DATEDIFF(ms,#ts,GETDATE());
-- fnMaxDate5, empty function call
set #i=1;
select #ts=GETDATE();
while #i<100000 begin select #md=dbo.fnMaxDate5(d1,d2) from #d; set #i+=1; end
select #ms5=DATEDIFF(ms,#ts,GETDATE());
select [Case(ms)]=#ms0/100000.0, [fnMaxDate5 (empty function call)]=#ms5/100000.0, fnMaxDate1=#ms1/100000.0, fnMaxDate2=#ms2/100000.0, fnMaxDate3 = #ms3/100000.0, fnMaxDate4=#ms4/100000.0
go
Lastly, here is the final version of the function:
/* Returns the greater of two dates.
SELECT dbo.fnMaxDate(NULL , NULL)
SELECT dbo.fnMaxDate('1/1/2011', NULL)
SELECT dbo.fnMaxDate(NULL , '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/2/2011', '1/1/2011')
SELECT dbo.fnMaxDate('1/1/2011', '1/2/2011')
*/
ALTER FUNCTION [dbo].[fnMaxDate]
(
#Date1 DATETIME,
#Date2 DATETIME
)
RETURNS DATETIME
AS
BEGIN
DECLARE #Result DATETIME
IF #Date1 IS NOT NULL AND #Date2 IS NOT NULL
IF #Date1 >= #Date2
SET #Result = #Date1
ELSE
SET #Result = #Date2
ELSE IF #Date1 IS NULL
SET #Result = #Date2
ELSE IF #Date2 IS NULL
SET #Result = #Date1
RETURN #Result
END