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.
Related
I have a Date Dimension which has the date column( having dates from 2010 to 2020) along with the Isworkday bit column (which is either 0 or 1). All the holidays are calculated and pre-populated in the dimension.
Now, I have a table which gives the start_date and end_datecolumns and I need to calculate the sum_of_workdays in those two date ranges using the date dimension.
(I know I can create a function which accepts start date and end date and returns sum of work days using date dimension but snowflake is really inefficient with functions hence i want to do with sub queries or joins or anything)
This is the function i currently use:
create or replace function Sum_Of_WorkDays(start_date TIMESTAMP, end_date TIMESTAMP)
returns int
as--to get sume of workdays in a given date range
$$
SELECT sum(ISWORKDAY)
FROM DATE_DIMENSION
WHERE "DATE" BETWEEN start_date AND end_date
$$
;
And below is how am calling the function from the table to calculate sum but takes lot of time if there are joins and cte involved in the query::
select Sum_Of_WorkDays(start_date,end_date) from table
Any efficient query for it other than using a function?
Conclusion: Ended up using Left join for each sum calculations to optimize it. Snowflake apparently sometimes is not that good in query optimization.
I hope someone could help with this?
I am building a report based on a stored procedure that has the following clause in it
where accountingperiod = #Accountingperiod or createddate between #Startdate and #Enddate
#Accountingperiod will be in the following Format 'Oct 2017'
#Start and #Enddates are just generic date formats.
I basically want my report to load and have the option to select whether the user wants to filter the report using the #Accountingperiod parameter or the date parameter (as both bring back entirely different data). Once the user has selected which one is to be used, the parameters (for example, #accountingperiod) will be available for selection.
How can this be achieved? Apologies if this is a silly question, I am quite new to SSRS!
Thank you
There are several ways to do this. The simplest would be to do it in the Stored Procedure and just test if Accounting Period has been set, if so use that, if not use the date range but that might not be intuitive for the user as they could select an accounting period AND a date range without realising that the date range would be ignored.
The most elegant solution would be to set the start and end dates based on the accounting period and have another entry in your accounting period list called 'Date Range' or 'Any' etc.
This assumes you can lookup or calculate the start and end dates for each accounting period. For the sake of simpicity in this example we'll assume that you have a table (say myAccPeriodTable) with the periods and date ranges in, something like this..
AccPeriodID AccPeriod StartDate EndDate
1 2017-Q1 2017-01-01 2017-03-31
2 2017=Q2 2017-04-01 2017-06-30
3 2017=Q3 2017-07-01 2017-09-30
etc...
Create a dataset (lets call it dsAccPeriods) with the following query
SELECT AccPeriodID, AccPeriod FROM myAccPeriodTable
UNION SELECT -1, 'Use Date range'
ORDER BY StartDate
You Accounting period Parameter (assume this is called #AccPeriodID) Available Values would be from a query and point to dsAccPeriods
The Value would be the AccPeriodID field and the Label field would be AccPeriod
Now create two more datasets say, dsDefaultStartDate and dsDefaultEndDate with the following queries respectively.
SELECT ISNULL(StartDate, 1999-01-01) AS StartDate From myAccPeriodTable WHERE AccPeriodID = #AccPeriodID
and
SELECT ISNULL(EndDate, 2020-12-31) AS EndDate From myAccPeriodTable WHERE AccPeriodID = #AccPeriodID
For your 'StartDate' parameter (assume its called #StartDate) the Default Value would simply point to the dsDefaultStartDate dataset and do the same with #EndDate pointing that to dsDefaultEndDate.
Now when the user selects a start date, the two data parameters should be populated with hte correct dates so your Stored Proc can simply filter based on the #StartDate and #EndDate parameters. If the user chooses the use Date Range option then the default dates will be set to whatever dates you specified in the dsDefaultStartDate and dsDefaultEndDate datasets.
Of course there is a chance that the user selects a real accounting period and then changes the date ranges. There are things you can do to avoid this but one step at a time !
I've written this answer without testing anything so there could be some mistakes but hopefully it will point you in hte right direction. If you have any issues leave a comment.
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;
I have a working query which takes too long to run. It is being used to populate an Access form field with a list of distinct contracts ordered by their start date.
The following query returns a list of distinct contract start dates for multiple commodities (which share contract start dates) where the contract start date (DELSTART) is greater or equal to the current date (PRICEDATE).
The function returndelivery returns a date attribute of the contract converted to a double, the function returnnumericdate just returns a double from a date (yyyymmdd).
SELECT DISTINCT (tblFuturesPrices.Period),
returnnumericdate(returndelivery([PERIOD],"S")) AS DELSTART,
ReturnNumericDate(Date()) AS PRICEDATE
FROM tblFuturesPrices
WHERE returnnumericdate(returndelivery([PERIOD],"S")) >= ReturnNumericDate(Date())
GROUP BY PERIOD
ORDER BY returnnumericdate(returndelivery([PERIOD],"S"));
Ideally I would like to refer to the variables DELSTART and PRICEDATE in the where clause but Access prompts for a variable value when I do so. I think the query takes longer than it should because I'm having to use my user defined functions numerous times.
The source table (tblFutures) contains prices for each commodity / contract for working days going back 6 months.
Thanks in advance.
I think the query takes longer than it should because I'm having to
use my user defined functions numerous times.
That's it. But you can reduce those functions:
returnnumericdate(returndelivery([PERIOD],"S")) >= ReturnNumericDate(Date())
will be no different from
returndelivery([PERIOD],"S") >= Date()
Don't know what returndelivery does.
Addendum:
Filter on the raw data and create a new function returndeliverydate that does the same as returndelivery except returns a Date value:
SELECT
tblFuturesPrices.Period,
returndeliverydate([PERIOD],"S") AS DELSTART,
Date() AS PRICEDATE
FROM
tblFuturesPrices
WHERE
returndeliverydate([PERIOD],"S") >= Date()
Save this query and use it as source in a new query:
Select Distinct
DELSTART,
PRICEDATE
FROM
YourQuery
I have a date of birth DATE column in a customer table with ~13 million rows. I would like to query this table to find all customers who were born on a certain month and day of that month, but any year.
Can I do this by casting the date into a char and doing a subscript query on the cast, or should I create an aditional char column, update it to hold just the month and day, or create three new integer columns to hold month, day and year, respectively?
This will be a very frequently used query criteria...
EDIT:... and the table has ~13 million rows.
Can you please provide an example of your best solution?
If it will be frequently used, consider a 'functional index'. Searching on that term at the Informix 11.70 InfoCentre produces a number of relevant hits.
You can use:
WHERE MONTH(date_col) = 12 AND DAY(date_col) = 25;
You can also play games such as:
WHERE MONTH(date_col) * 100 + DAY(date_col) = 1225;
This might be more suitable for a functional index, but isn't as clear for everyday use. You could easily write a stored procedure too:
Note that in the absence of a functional index, invoking functions on a column in the criterion means that an index is unlikely to be used.
CREATE FUNCTION mmdd(date_val DATE DEFAULT TODAY) RETURNING SMALLINT AS mmdd;
RETURN MONTH(date_val) * 100 + DAY(date_val);
END FUNCTION;
And use it as:
WHERE mmdd(date_col) = 1225;
Depending on how frequently you do this and how fast it needs to run you might think about splitting the date column into day, month and year columns. This would make search faster but cause all sorts of other problems when you want to retrieve a whole date (and also problems in validating that it is a date) - not a great idea.
Assuming speed isn't a probem I would do something like:
select *
FROM Table
WHERE Month(*DateOfBirthColumn*) = *SomeMonth* AND DAY(*DateOfBirthColumn*) = *SomeDay*
I don't have informix in front of me at the moment but I think the syntax is right.