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
Related
My json is
[{"Date":"2022-10-27","Delta":60,"Comment":null},{"Date":"2022-10-26","Delta":60,"Comment":null},{"Date":"2022-10-25","Delta":60,"Comment":null}]
I need to check that all Date values are greater than the current time. If so, return true, otherwise false.
I tried to do something like this:
SELECT CASE WHEN EXISTS (SELECT * FROM XXX WHERE Dates < GETDATE())
THEN CAST(0 AS BIT)
ELSE CAST(1 AS BIT) END
But I need a table XXX with all the Dates from my json. How do I get them?
And am I even thinking the right way to do this, or is there a better option?
DECLARE #json nvarchar(max) = N'[
{"Date":"2022-10-27","Delta":60,"Comment":null},
{"Date":"2022-10-26","Delta":60,"Comment":null},
{"Date":"2022-10-25","Delta":60,"Comment":null}
]';
SELECT CASE WHEN EXISTS
(
SELECT 1 FROM OPENJSON(#json) AS x
CROSS APPLY OPENJSON(value) AS y
WHERE y.[key] = 'Date'
AND TRY_CONVERT(date, y.value, 120) < GETDATE()
) THEN 0 ELSE 1 END;
You can put this in a function:
CREATE FUNCTION dbo.SniffOutBadDates
(
#json nvarchar(max),
#key nvarchar(128),
#when datetime
)
RETURNS TABLE
AS
RETURN
(
SELECT AllDatesAreGood = CASE WHEN EXISTS
(
SELECT 1 FROM OPENJSON(#json) AS x
CROSS APPLY OPENJSON(value) AS y
WHERE y.[key] = #key
AND TRY_CONVERT(date, y.value, 120) < #when
) THEN 0 ELSE 1 END
);
Then call it against a table, like this:
SELECT t.id, f.AllDatesAreGood
FROM dbo.YourTableName AS t
CROSS APPLY dbo.SniffOutBadDates
(t.jsonColumn, 'Date', GETDATE()) AS f;
Working example in this fiddle.
If you parse the input JSON using OPENJSON() with explicit schema (the WITH clause), you need a single statement:
SELECT IIF(
COUNT(*) = COUNT(CASE WHEN TRY_CONVERT(date, [Date], 23) > GETDATE() THEN 1 END),
1,
0
) AS [Result]
FROM OPENJSON(#json) WITH ([Date] varchar(10))
And if you want to use your current statement:
SELECT
CASE
WHEN EXISTS (
SELECT 1
FROM OPENJSON(#json) WITH ([Date] varchar(10))
WHERE TRY_CONVERT(date, [Date], 23) < GETDATE()
) THEN CAST(0 AS BIT)
ELSE
CAST(1 AS BIT)
END AS Result
I have a routine. But it' s too slow. How can I improve the query?
My records: http://www.sqlfiddle.com/#!9/14cceb/1/0
My query:
CREATE DEFINER = 'root'#'localhost'
PROCEDURE example.ssa()
BEGIN
drop table if exists gps_table;
drop table if exists exam_datas;
CREATE TEMPORARY TABLE gps_table(ID int PRIMARY KEY AUTO_INCREMENT,timei
int,
trun_date_time datetime, tadd_meter int, tin_here int null);
insert into gps_table(timei,trun_date_time,tadd_meter,tin_here) select
imei, run_date_time, add_meter, in_here from example_table;
CREATE TEMPORARY TABLE exam_datas(ID int PRIMARY KEY AUTO_INCREMENT,vimei
int, vbas_run_date_time datetime, vbit_run_date_time datetime, vdifff int);
select tin_here from gps_table limit 1 into #onceki_durum;
select count(id) from gps_table into #kayit_sayisi;
set #i = 1;
set #min_mes = 0;
set #max_mes = 0;
set #frst_id = 0;
set #imei = 0;
set #run_date_time = '0000-00-00 00:00:00';
set #run_date_time2 = '0000-00-00 00:00:00';
myloop: WHILE (#i <= #kayit_sayisi) DO
select tin_here from gps_table where id = #i into #in_here_true;
if (#in_here_true = 1) then
select id,trun_date_time, tadd_meter from gps_table where id = #i into #frst_id,#run_date_time2, #min_mes;
select id from gps_table where id > #frst_id and tin_here =0 order by id asc limit 1 INTO #id;
SET #id = #id-1;
select id, timei, trun_date_time, tadd_meter from gps_table
where id = #id and tin_here =1 limit 1 into #i, #imei, #run_date_time, #max_mes;
if(#i-#frst_id>3) then
set #i:=#i+1;
insert into exam_datas(vimei,vbas_run_date_time,vbit_run_date_time,vdifff) Values (#imei, #run_date_time2, #run_date_time, #max_mes-#min_mes);
SELECT * FROM exam_datas;
SET #asd =1;
elseif 1=1 then
set #i:=#i+1;
End if;
ELSEIF 1=1
THEN SET #i:=#i+1;
End if;
IF (#i = #kayit_sayisi)
THEN set #tamam =1; LEAVE myloop;
END IF;
END WHILE myloop;
select DISTINCT * from exam_datas;
drop table if exists exam_datas;
drop table if exists gps_table;
END
I need: id= 6 first true and id= 11 last_true
firs_trure - last_true = 304-290= 14
id=14 first true and id=18 last_true
firs_true - last_true = 332-324= 8
This routine is too slow.
MySql version is 5.7 and There are 2 milions record in the table.
UPDATE:
Query is here. HERE
Thank you #LukStorms
It's possible to get such results in 1 query.
Thus avoiding a WHILE loop over records.
This example works without using window functions. Just using variables inside the query to calculate a rank. Which is then used to get the minimums and maximums of the groups.
select
imei,
min(run_date_time) as start_dt,
max(run_date_time) as stop_dt,
max(add_meter) - min(add_meter) as diff
from
(
select imei, id, run_date_time, add_meter, in_here,
case
when #prev_imei = imei and #prev_ih = in_here then #rnk
when #rnk := #rnk + 1 then #rnk
end as rnk,
#prev_imei := imei as prev_imei,
#prev_ih := in_here as prev_ih
from example_table t
cross join (select #rnk := 0, #prev_ih := null, #prev_imei := null) vars
order by imei, id, run_date_time
) q
where in_here = 1
group by imei, rnk
having count(*) > 4
order by imei, min(id);
In the procedure such query can be used to fill that final temporary table.
A test on db<>fiddle here
I need to create a temporary table that is populated based on two parameters:
declare #Start date = '01/01/2015'
declare #End date = '12/31/2015'
The temporary table should have a column that will capture YYYYMM for all the years and month that are between #Start and #End parameter.
Here's what I have so far. I want to stop it at 201412 and then start again at 201501. Instead, this loop keeps going in increment of plus 1 (I do not want to see 201413..so on):
declare #Start date = '01/01/2014'
declare #End date = '12/31/2015'
declare #monthstart as int
declare #monthend as int
declare #increment as int
set #monthstart = (SELECT LEFT(CONVERT(varchar, #Start,112),6))
set #monthend = (SELECT LEFT(CONVERT(varchar, #End,112),6))
create table #datetemp (RelevantYYYYMM int)
insert into #datetemp values (#monthstart)
set #increment = #monthstart
While #increment < #monthend
BEGIN
set #increment = (select Max(RelevantYYYYMM) + 1 from #datetemp)
insert into #datetemp values (#increment)
set #increment = (select Max(RelevantYYYYMM) from #datetemp)
IF (select Max(RelevantYYYYMM) from #datetemp) > #monthend
Break
else
continue
END
select * from #datetemp
You can use tally table and avoid loop:
CREATE TABLE #datetemp (RelevantYYYYMM INT);
DECLARE #Start DATE = '01/01/2015', #End DATE = '12/31/2015';
WITH tally_table AS
(
SELECT TOP 1000 rn = ROW_NUMBER() OVER(ORDER BY name) - 1
FROM master..spt_values
)
INSERT INTO #datetemp(RelevantYYYYMM)
SELECT LEFT(CONVERT(varchar, DATEADD(month, rn, #Start),112),6)
FROM tally_table
WHERE YEAR(DATEADD(month, rn, #Start)) <= YEAR(#End)
AND MONTH(DATEADD(month, rn, #Start)) <= MONTH(#End)
SELECT *
FROM #datetemp;
LiveDemo
SELECT
PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName,
STORE_ID, STORE_CODE, STORE_NAME,
ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname,
T.TimeIn, T.TimeOut, T.PlannedDate, T.Reason, TaskCode, TotalTime
FROM
[dbo].Report_RD_Coverage T
INNER JOIN
#TempLocationH TL ON TL.LocationId=T.Location_Id
WHERE
CONVERT(Date, PDADate) Between (#Start_Date) AND Isnull(#End_Date, #CurrentDate)
AND T.Account_Id IN
(SELECT
CASE WHEN #Account_Id IS NULL THEN T.Account_Id
ELSE (SELECT * FROM UDF_SplitString(#Account_Id,','))
END
)
AND T.StoreType_Id IN
(SELECT
CASE WHEN #StoreType_Id IS NULL THEN T.StoreType_Id
ELSE (SELECT * FROM UDF_SplitString(#StoreType_Id,','))
END
)
AND T.Store_Id IN
(SELECT
CASE WHEN #Store_Id IS NULL THEN T.Store_Id
ELSE (SELECT * FROM UDF_SplitString(#Store_Id,','))
END
)
If #Account_Id, #StoreType_Id and #Store_Id are null the it should select all the ACCOUNT_ID, STORETYPE_ID and STORE_ID otherwise based on parameter value it should filter.
UDF_SplitString is the function to split up comma-separated strings, and its return value is a table like:
- 1
- 2
- 3
I'm getting this error:
Subquery returned more than 1 value. This is not permitted when the subquery follows =, !=, <, <= , >, >= or when the subquery is used as an expression.
CASE must return a scalar value, so try this variation instead:
select PDADate, T.Merchandizer_ID, T.Merchandizer, Merchandizer_LoginName, STORE_ID, STORE_CODE,
STORE_NAME, ACCOUNT_ID, ACCOUNT_NAME, Account_Store_Format_Id, Account_Store_Format,
StoreType_Id, StoreType, T.Listid, T.Listname, T.TimeIn, T.TimeOut, T.PlannedDate,
T.Reason, TaskCode, TotalTime
from [dbo].Report_RD_Coverage T
inner join #TempLocationH TL on TL.LocationId = T.Location_Id
where CONVERT(date, PDADate) between (#Start_Date)
and Isnull(#End_Date, #CurrentDate)
and (
#Account_Id is null
or T.Account_Id in (
select *
from UDF_SplitString(#Account_Id, ',')
)
)
and (
#StoreType_Id is null
or T.StoreType_Id in (
select *
from UDF_SplitString(#StoreType_Id, ',')
)
)
and (
#Store_Id is null
or T.Store_Id in (
select *
from UDF_SplitString(#Store_Id, ',')
) end
)
I tried this and reached very closer but you have to do something from what I found a link.
This is my try. the only thing you need to build is the #udf data.
declare #Store_Id INT;
declare #Account_Id INT;
DECLARE #UDF[9] OF VARCHAR(30);
set #Store_Id = 99 --NULL
set #Account_Id = 15
SET #UDF = '11,12,13,14,15,16'
SELECT #Account_Id AS ACID
WHERE CAST(#Account_Id AS VARCHAR(6)) IN (
CASE WHEN #Store_Id IS NULL THEN CAST(#Account_Id AS VARCHAR(6))
ELSE #UDF END
The link is at
http://www.codeproject.com/Questions/473174/CreateplusArrayplusinplusSqlplusServer
DECLARE #INSTR as VARCHAR(MAX)
SET #INSTR = '2,3,177,'
DECLARE #SEPERATOR as VARCHAR(1)
DECLARE #SP INT
DECLARE #VALUE VARCHAR(1000)
SET #SEPERATOR = ','
CREATE TABLE #tempTab (id int not null)
WHILE PATINDEX('%' + #SEPERATOR + '%', #INSTR ) <> 0
BEGIN
SELECT #SP = PATINDEX('%' + #SEPERATOR + '%',#INSTR)
SELECT #VALUE = LEFT(#INSTR , #SP - 1)
SELECT #INSTR = STUFF(#INSTR, 1, #SP, '')
INSERT INTO #tempTab (id) VALUES (#VALUE)
END
SELECT * FROM myTable WHERE id IN **(SELECT id FROM #tempTab)**
DROP TABLE #tempTab
you can extract for the sql in bold and the logic how to create temp table and its data and I hope you will get what you want.
> This is the my right solultion........now its working correctly
CREATE TABLE #Store_Id (StoreID varchar(20))
IF #Store_Id != '0'
BEGIN
INSERT INTO #Store_Id
SELECT data FROM UDF_SplitString(#Store_Id,',')
END
ELSE
BEGIN
INSERT INTO #Store_Id
SELECT '0'
END
CREATE TABLE #StoreType_Id (StoreTypeID varchar(20))
IF #StoreType_Id != '0'
BEGIN
INSERT INTO #StoreType_Id
SELECT data FROM UDF_SplitString(#StoreType_Id,',')
END
ELSE
BEGIN
INSERT INTO #StoreType_Id
SELECT '0'
END
CREATE TABLE #Account_Id (AccountID varchar(20))
IF #Account_Id != '0'
BEGIN
INSERT INTO #Account_Id
SELECT data FROM UDF_SplitString(#Account_Id,',')
END
ELSE
BEGIN
INSERT INTO #Account_Id
SELECT '0'
END
INSERT INTO #FinalTable(VisitDate,Merchandizer_Id,Merchandizer,MerchandizerLogin,StoreId,StoreCode,StoreName,AccountId,AccountName,
Account_Store_Format_Id,Account_Store_Format,StoreTypeId ,StoreType ,ListId ,ListName,TimeIn ,TimeOut,PlannedDate ,Reason ,TaskCode,TotalTime)
SELECT Visit_Date,T.Merchandizer_ID,T.Merchandizer,Merchandizer_LoginName,STORE_ID,STORE_CODE,STORE_NAME,ACCOUNT_ID,ACCOUNT_NAME,
Account_Store_Format_Id,Account_Store_Format,StoreType_Id,
StoreType,T.Listid,T.Listname,T.TimeIn,T.TimeOut,T.PlannedDate,T.Reason,TaskCode,TotalTime
FROM [dbo].Report_RD_Coverage T
INNER JOIN #TempLocationH TL ON TL.LocationId=T.Location_Id
INNER JOIN #Store_Id on CONVERT(VARCHAR,t.Store_Id) = CASE WHEN #Store_Id = '0' THEN convert(VARCHAR,t.Store_Id) ELSE StoreID END
INNER JOIN #StoreType_Id on CONVERT(VARCHAR,t.StoreType_Id) = CASE WHEN #StoreType_Id = '0' THEN convert(VARCHAR,t.StoreType_Id) ELSE StoreTypeID END
INNER JOIN #Account_Id on CONVERT(VARCHAR,t.Account_Id) = CASE WHEN #Account_Id = '0' THEN convert(VARCHAR,t.Account_Id) ELSE AccountID END
WHERE CONVERT(Date,PDADate) Between #Start_Date AND #End_Date
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.