SQL CHARINDEX, SUBSTIRNG, PARSENAME better for Performance - sql

I have a table [Evetns]- rows of
EventName, EventDateTime
Sample, 25/12/2000
I have another table with period sets as DateRange type
period_range
1/1/1999,1/1/2001
1/1/1999,24/12,2000
So the result would be
Sample, 1
The event sample with event date 25/12/2000 is found in one range of the period data.
For this I have created a function GetRange() as below
select
#var=count(*)
--, convert(datetime,PARSENAME(REPLACE(period_range,',','.'),2),103),
--convert(datetime,PARSENAME(REPLACE(period_range,',','.'),1),103)
from
[dbo].[DateRange]
where
#date between convert(datetime,PARSENAME(REPLACE(period_range,',','.'),2),103)
and convert(datetime,PARSENAME(REPLACE(period_range,',','.'),1),103)
the function receive the date from the Events table and pass it to above function which returns and int value and I am consuming the function as below,
select eventname,dbo.[getrange](eventdate) exist from [dbo].[Evetns]
The result set satisfies the requirement but need some suggestion for better performance. which should be use out of this?
Which function will be good for performance CHARINDEX, SUBSTIRNG or PARSENAME?
Is that good idea for bulk records?
any suggestions will be highly appreciated.

Related

What is the fastest way to populate table with dates after certain day?

Let's assume that we have the following input parameters:
date [Date]
period [Integer]
The task is the following: build the table which has two columns: date and dayname.
So, if we have date = 2018-07-12 and period = 3 the table should look like this:
date |dayname
-------------------
2018-07-12|THURSDAY
2018-07-13|FRIDAY
2018-07-14|SATURDAY
My solution is the following:
select add_days(date, -1) into previousDay from "DUMMY";
for i in 1..:period do
select add_days(previousDay, i) into nextDay from "DUMMY";
:result.insert((nextDay, dayname(nextDay));
end for;
but I don't like the loop. I assume that it might be a problem in the performance if there are more complicated values that I want to put to result table.
What would be the better solution to achieve the target?
Running through a loop and inserting values one by one is most certainly the slowest possible option to accomplish the task.
Instead, you could use SAP HANA's time series feature.
With a statement like
SELECT to_date(GENERATED_PERIOD_START)
FROM SERIES_GENERATE_TIMESTAMP('INTERVAL 1 DAY', '01.01.0001', '31.12.9999')
you could generate a bounded range of valid dates with a given interval length.
In my tests using this approach brought the time to insert a set of dates from ca. 9 minutes down to 7 seconds...
I've written about that some time ago here and here if you want some more examples for that.
In those examples, I even included the use of series tables that allow for efficient compression of timestamp column values.
Series Data functions include SERIES_GENERATE_DATE which returns a set of values in date data format. So you don't have to bother to convert returned data into desired date format.
Here is a sample code
declare d int := 5;
declare dstart date := '01.01.2018';
SELECT generated_period_start FROM SERIES_GENERATE_DATE('INTERVAL 1 DAY', :dstart, add_days(:dstart, :d));

Using a UDF function in a query

I have the following Code which points at the DateDimension which works out the actual mins of business opening hours and closing ours. I am hoping to use the output of the query to pass on to my main query to identify the sum total of minutes business is open. This will allow me to exclude bank holidays and sundays if necessary. However I am having problems creating the function. Cannot find either column "dbo" or the user-defined function or aggregate "dbo.GetWorkingDaysMin", or the name is ambiguous.
this end query I expect to look like this
SELECT dbo.GetWorkingDaysMin([WebLeadRecd_DKey],[ContactSucces_DKey]), COLUMN1, column2 etc AS Name
FROM [dbo].[TEST_DATES]
this is the function below
alter FUNCTION GetWorkingDaysMin
(
#Date1 INT,
#Date2 INT
)
RETURNS table AS
RETURN
(
SELECT SUM(TotalMinsOpen) AS TotalMinOpen, SUM(TotalMinsClosed) AS TotalMinClosed,
FROM [dbo].[DIM_DATE]
WHERE DateKey BETWEEN #Date1 AND #Date2
)
I am just wondering if this is the best way to exclude bank holidays and sundays, the opening hours of the business are 8am - 6pm Mon -Fri and Satu 8am - 1pm. Also perhaps you can advise on the next stage as well, I am thinking about using cases statements to do a bit of airthmetics but am I setting myseld up for a failure taking that approach or is there a better way?
You have defined a table valued function because you are returning two values. Then you are using it as a scalar function. Instead, call it as:
SELECT wdm.*, td.*
FROM dbo.TEST_DATES td CROSS APPLY
dbo.GetWorkingDaysMin(td.WebLeadRecd_DKey, td.ContactSucces_DKey) wdm;

Last DateTime from JSON in Azure Stream Analytics

I am having an issue in ASA when trying to get the "Max" DateTime.
My code is:
LAST(Timestamp) OVER (PARTITION BY DeviceId LIMIT DURATION(minute, 5)) AS DateTime,
It is coming up with an error saying it is not in an aggregate function or in the group by. Im not sure what I am doing wrong here. Any help would be appreciated!
LAST is not an aggregate function and cannot be used in GROUP BY statements. It is most typically used in SELECT statements together with WHEN clause to "look back" and find event matching specific condition. Please check examples here
If what you want is to find biggest timestamp in the time window, you can do something like this:
SELECT MAX(CAST(Timestamp AS DateTime)) AS DateTime
FROM input
GROUP BY DeviceId, TumblingWindow(minute, 1)

Access 2007 query date calculation

I have the following Access query (see above) to give me the date, X number of weeks out from the actual WorkDte that exists in the table. But, the date these expressions calculate out may not actually exists in the “CIB_Results” table due to a bank holiday etc. Is there a way to generate the same sort of data but say if it’s running the “Wk1” calculation and it calculates out 1/1/2016 (which does not exists due to the new year holiday), instead of doing [WorkDte]-7 it will move on to [WorkDte]-14 and so on, until it finds an actual date that exists in the “CIB_Results” table? I’m wanting to apply the same logic to all the fields in the query…that way they will all self adjust based off of the actual dates that exist in the “CIB_Results” table. Any help with this would be greatly appreciated!
Have a function IsHoliday(SomeDate) that looks up SomeDate in your holiday table and returns True if found.
Then create a loop:
Public Function PreviousWorkWeekday(ByVal SomeDate As Date) As Date
Do
SomeDate = DateAdd("ww", -1, SomeDate)
Loop Until Not IsHoliday(SomeDate)
PreviousWorkWeekday = SomeDate
End Function
Now use function PreviousWorkWeekday in your query.

Greatest date from list of date

I have this simple data base:
7/2/2013
7/13/2013
I write a simple SQL statement to select the greatest date from a list of date. I try to use the (max function) as follow:
select max([P_Date]) from [BalDB].[dbo].[tab_Product]
The result was incorrect; it gives me the smallest date not the greatest as follow:
7/2/2013
So please help me to know what is the problem in my SQL statement and how can I solve it
Problem: Get the greatest date from a list of date or compare it with local date and take the greater!!
The sql max function returns the largest value of the selected column, in your case since your data type is a nvarchar the largest value is what is alphabetically larger, which in this case is 7/2/2013 (since the "2" is greater then the "1" in "13").
What you need to do is basically what #David mentioned, either chance the data type of the column or if it isn't feasible then you can cast it in your query as a datetime
For example
select max(cast([P_Date] as datetime)) from [BalDB].[dbo].[tab_Product]
The max function is making this slower than it needs to be, try this.
select top 1 convert(datetime,P_Date) from [BalDB].[dbo].[tab_Product] order by convert(datetime,P_Date) desc
Now your dates should be date types, not varchars, but for the sake of querying your data as is, this will work.