I'm running a series of reports where time window called in query is rolling, and individual per report.. Some reports look 400 days back, others look 10 weeks back, while others again look at -40days/+80days... and so on - many options.
All reports are scheduled in daily or weekly runs, meaning setting prompts will require a manual reset of prompt for every instance through the scheduler. Not optimal.
I know the universe designer can design specific filters to drag into the queries using the query designer, but with so many different options, I find it a bit of an issue that the universe designer should create specific filters for these specific purposes, adding a vast number of specific filters intended for specific use to various universes.
I'm after an option where it is possible to assign a calculation to a date field, which stay fixed for the purpose of the report for every scheduled instance.
For instance, looking at invoice date from 400 days before today and onwards would look like Where DIM_TIME_INV.DAY_DAY >= sysdate -400 - This I can hardcode into the SQl of the specific report, and it will stay through the scheduler and roll 1 day for every day the report is run. But if I decide to make a change in the query elements, the SQl is screwed, and I will have to manually add the modification to the SQL again.
I found an article reg. the use of #Prompt and would ask universe designer to try and sandbox this in our version of BO.
While I'm being impatient, I try myself using following code based on example 4 from linked article.
SELECT
#select('DIM_TIME_INV.DAY_DAY') >= sysdate -(#prompt('Invoiced, days before today:','N',[DIM_TIME_INV.DAY_DAY],mono,free))
FROM
DIM_TIME_INV
Testing the SQL gives following error:
ORA-00936
SAP kba 2054721
The whole idea is to have a flexible yet consistent dimension that will calculate every time the report is run, without losing the code whenever new items are added to the report.
Does anyone know of a way to use the #Prompt in SQL for SAP WEBI 4.2? - Or any other way to have 'flexible' time dimensions where it is possible to set a from-date or to-date independently or even a range, without having universe designer creating a s**t-load of filters and dump in various universes.
Thanks // C
With regard to your example code, I think you're on the right track but your syntax has some issues:
SELECT
#select('DIM_TIME_INV.DAY_DAY') >= sysdate -(#prompt('Invoiced, days before today:','N',[DIM_TIME_INV.DAY_DAY],mono,free))
FROM
DIM_TIME_INV
First, both #Select and #Prompt must refer to universe objects, not columns. The syntax for both is: class name\object name. Assuming that the DIM_TIME_INV.DAY_DAY is associated with a universe object named Day Day in a class named Dim Time, the above code should be:
SELECT
#select('Dim Time\Day Day') >= sysdate -(#prompt('Invoiced, days before today:','N','Dim Time\Day Day',mono,free))
FROM
DIM_TIME_INV
Also note that the object reference in the #prompt call is delimited by single quotes, not brackets.
Next, I'm assuming that DAY_DAY is a date field. Its reference in the #prompt call would cause the prompt to display a list of values, sourced from DAY_DAY. But you want a numeric value from the prompt, not a date, so I would just leave that out, which will let the users enter a numeric value:
SELECT
#select('Dim Time\Day Day') >= sysdate -(#prompt('Invoiced, days before today:','N',,mono,free))
FROM
DIM_TIME_INV
Next, even with this corrected syntax, there will be an issue using this code as you have it. A good way to debug #prompt issues is to view the SQL in the WebI report after you get the error -- the SQL will show the rendered result, with all functions (#select and #prompt) expanded. For the above, you might get SQL like:
SELECT
DIM_TIME_INV.DAY_DAY >= sysdate -(400)
FROM
DIM_TIME_INV
This, of course, is invalid - you can't have a condition in the SELECT clause. If this is truly intended to be a condition (which I think it is, based on your objective), then it should be a predefined condition rather than a dimension.
With that said, I think you're on the right track for what you want to do. With the above corrections, you would have a predefined condition that you could drop into reports, which would enable the users to select the starting period (by number of days ago) for the report. You could create additional prompts with different logic, ex:
#select('Dim Time\Day Day') >= sysdate -(#prompt('Invoiced, weeks before today:','N',,mono,free) * 7)
or
#select('Dim Time\Day Day')
BETWEEN sysdate - #prompt('Starting days ago:','N',,mono,free)
AND sysdate - #prompt('Ending days ago:','N',,mono,free)
Related
I've got a question and it may sound dumb but am figuring it out as I go...
In SSRS there is an option to have a data driven query and in that you can edit the dataset to read parameters of the report who to send to ect., ect.,
Is there a way to have the query read an output of a subquery and if it doesn't equal the output it doesn't send but if it does, it does trigger the report sending?
In this particular example, the report needs to be triggered to send on the 3rd business day of the month. I have a query that reads the third business day written up but I am not sure how to get it into the query and read as if the date = 2023/01/04 then trigger report and send it off, otherwise do nothing, checking daily if it is that date.
In my business day query it has the columns, Date - which is the date, DayOfWeek - which is the numeral day of the week 2-6(for weekdays), Year, Month, Day, and Working day of the month(which is all 3s being the third business day.)
Should I have the query set to reading if workingdayofmonth = 3 then trigger the report? Would that be the easiest? I am not entirely sure how to code it as such into the SSRS data driven query.
Thank you for your time and help!
If you are using Enterprise edition, you can setup a data driven subscription.
I don't use Enterprise so I can't give a working exmaple but essentially, you create a dataset for the subscription that will only return data if your conditions are met.
As you previous question (linked here for other users reference) got you a calendar view that gives you the days the report needs to run, you can use that view, something like
SELECT * FROM myCalendarView WHERE TheDate = CAST(GetDate() AS Date)
The subscription will attempt to run everyday (or whatever the schedule is) but it will not produce anything unless the query above returns a resultset.
Take a look at this post which is similar to what you are attempting.
https://social.msdn.microsoft.com/Forums/sqlserver/en-US/88b6c7ec-3cba-4b5f-b09d-c098dc933063/how-to-modify-an-ssrs-subscription-to-only-run-first-monday-of-every-fiscal-month?forum=sqlreportingservices
Hope I can explain the problem I'm having trouble with.
I have to write a stepwise methodology using pseudocode/SQL query to auto generate a list of products/items with low stock/expiry from the inventory database.The list must be updated at 12 a.m. daily.
I tried this
CREATE EVENT IF NOT EXISTS update_table
ON SCHEDULE EVERY 1 DAY STARTS '2022-05-22 00:00:00'
ON COMPLETION PRESERVE ENABLE
Do
Select inventory.products from inventory where inventory.stocks <
inventory.required_stocks.
Your stated requirement is to run some sort of report very soon after the beginning of each calendar day.
The next question you must answer is this: What will you do with that report? Will you simply drop it into "low_stock" table someplace in your database? Will you format it into an email message and send it to your purchasing department? It will be difficult to make "pseudocode" for your requirement without first analyzing the overall business process you intend to enhance.
Various RDBMS systems have ways of doing scheduled things at particular times of day. You've shown the EVENT setup provided by MariaDB / MySQL. SQL Server has their "Jobs" system. postgreSQL has the pg_cron extension. Yo
The thing is, you can't just do SELECT operations from within these scheduled database actions: the result sets have noplace to go from that context. You can do CREATE TABLE midnight_run AS SELECT whatever ... to place the results in a table. But then the results are in another table.
If you want to get the results out of the DBMS, you'll need a UNIXish cron job or a Windowsish scheduled task running an appropriate application at midnight each day.
Pro tip Do your best to avoid scheduling stuff for precisely midnight. Many things run then. If you wait until a couple of minutes after the hour, your code is less likely to contend with other midnight code.
There are some views which has columns with formula including #now. These columns are used to calculate days from now. But these views are so slow. I just need to get documents in specific category from result of view. Are there any setting in view to get category's document before calculate days? Or do I have to remove days columns from view and write an agent to add&calculate days columns to the view's result?
"Or [do] I have to remove days columns from view and write an agent to add&calculate days columns to the view's result?"
Yes. #Now in a view formula is a recipe for poor performance. Create a scheduled agent that runs once per day and updates a field on the document then show that field in the view.
This column formula allows you to add a Today value without using #Today and hence lots of continual processing;
TodayDateString:= "Today";
Today := #TextToTime(TodayDateString);
#Abs(#Integer((Today - DateToCompare) / (60 * 60 * 24)))
Already answered, but I still felt the need to add my thoughts.
If you can afford to touch your documents every day (e.g. it's just a web on a single or clustered server) then I'd seriously consider writing an agent that updates a "NumDaysOld" field.
The reason why performance is slow if you have #Now or #Today in a view selection or column formula is because the indexer then knows that it is time-dependent and therefore doesn't store the view index (or maybe just doesn't store the entire index, I'm not sure), causing it to rebuild every time it's accessed.
If you cheat this by using #TextToTime("Today") then your view indexes risk being out of date because if a document doesn't change for n days, the view doesn't change for n days, and the indexer isn't triggered...
Perhaps a best practice would be to write an agent to change the column formula every day so that instead of #Today, use a literal date (by using square brackets, like [5/29/2018]) and then write an agent to change that column formula every day. I've never tried that because that wasn't available to me when I had needed to do something like this. (It's been a long time.) Instead I have resolved this need by:
writing an agent that modified each document to update the age of the document, or
making folders for "< 1 month", "2 to 6 months", etc., and had a daily agent that would populating/correct the folders, or
avoiding the problem by having a view of open documents sorted by date and then trying to convince the end-users that was close enough! :-P (not proud of this one)
i have a database used at work for evaluating calls, the database is somewhat dated and originally created on Access XP. Once evaluated these calls are given a score out of 5 which is entered along with other data (such as date, employee name, etc) on a form. I have the reports set up so they generate when you enter the employee name and then the start of a date period and the end of a date period, the report will then generate and show the entries made between those 2 dates. i am trying to include a section on the report which shows an average of the call score for the employee for the period chosen. I understand this may be pretty simple but i'm struggling! cheers, Kris
If you want to work out group calculations on reports, you can either put them in the group header/footer, or report header/footer (for calculations over the whole report).
In this case, placing a textbox with something like =AVG([CallScore]) as the control source in the Report Footer should work.
This page should explain more about using aggregate functions in reports: http://office.microsoft.com/en-gb/access-help/summing-in-reports-HA001122444.aspx
We are currently developing an application in which multiple entities have associated opening hours. Opening hours may span multiple days, or may be contained within a single day.
Ex. Opens Monday at 6:00 and closes at Friday at 18:00.
Or
Opens Monday at 06:00 and closes Monday at 15:00.
Also, an entity may have multiple sets of opening hours per day.
So far, the best design I have found, is to define an opening hour to consist of the following:
StartDay, StartTime, EndDay and EndTime.
This design allows for all the needed flexibility. However, data integrity becomes an issue. I cannot seem to find a solution that will disallow overlapping spans (in the database).
Please share your thoughts.
EDIT: The database is Microsoft SQL Server 2008 R2
Consider storing your StartDay and StartTime, but then have a value for the number of hours that it's open. This will ensure that your closing datetime is after the opening.
OpenDate -- day of week? e.g. 1 for Monday
OpenTime -- time of day. e.g. 08:00
DurationInHours -- in hours or mins. e.g. 15.5
Presuming a robust trigger framework
On insert/update you would check if the new start or end date falls inside of any existing range. If it does then you would roll back the change.
CREATE TRIGGER [dbo].[mytable_iutrig] on [mytable] FOR INSERT, UPDATE AS
IF (SELECT COUNT(*)
FROM inserted, mytable
WHERE (inserted.startdate < mytable.enddate
AND inserted.startdate > mytable.startdate)
OR (inserted.enddate < mytable.enddate
AND inserted.enddate > mytable.startdate)) > 0
BEGIN
RAISERROR --error number
ROLLBACK TRANSACTION
END
Detecting and preventing overlapping time periods will have to be done at the application level. Of course you can attempt to use a trigger in the database but in my opinion this is not a database issue. The structure that you came up with is fine, but your application logic will have to take care of the overlap.
There's an article by Joe Celko on the SimpleTalk website, over here, that discusses a similar issue, and presents am elegant if complex solution. This is probably applicable to your situation.
A table with a single column TimeOfChangeBetweenOpeningAndClosing?
More seriously though, I would probably not worry too much about coming up with a single database structure for representing everything, eventually you'll probably want want a system involving recurrences, planned closures etc. Persist objects representing those, and then evaluate them to find out the closing/opening times.
This looks like a good solution, but you'll have to write a custom validation function. The built in database validation (i.e. unique, less than x, etc.) isn't going to cut it here. To ensure you don't have overlapping spans, every time you insert a record into the database, you're going to have to select existing records and compare...
First the logic, two spans will overlap if the start value of one falls between the start/end of the other. This is much easier if we have datetimes combined, instead of date1,time1 and date2,time2. So a query to find an overlap looks like this.
select openingId
from opening o1
join opening o2 on o1.startDateTime
between o2.startDateTime
AND o2.endDateTime
You can put this into a trigger and throw an error if a match is found.