At work, I've been designing an MS Access query to manipulate client service agreements.
The requirement I'm stuck on is that if a client has had multiple consecutive agreements (i.e. the start date of one is the day after the end date of the previous one), they're counted as one (so the earliest start date is used).
The relevant fields in the table are:
Agr_ID (Agreement ID), number
Per_ID (Person ID), text
Agr_Type (Agreement Type), text
Start_Date, date
End_Date, date
For example:
103, A1234, Homecare, 20th Oct 2013, 05th Nov 2013
110, A1234, OT Equip, 06th Nov 2013, 09th Dec 2013
114, A1234, Homecare, 10th Dec 2013, 19th Jan 2014
125, A1234, Homecare, 20th Jan 2014, 15th Jun 2014
147, A1234, Homecare, 16th Jun 2014, null
The last three would be considered a single agreement (spanning the date range 10th Dec 2013 to present) but the top two wouldn't (103 isn't consecutive with 114, 110 is of a different type). The latest agreement is to be used as the base, as subsequent queries will only keep those combined agreements whose end date is later than [Prompt] and which have been open for at least 365 days. So unfortunately, grabbing min(Start_Date) won't do.
So the desired result for that extract would be:
103, A1234, Homecare, 20th Oct 2013, 05th Nov 2013
110, A1234, OT Equip, 06th Nov 2013, 09th Dec 2013
147, A1234, Homecare, 10th Dec 2013, null
I'm thinking several derived tables / subqueries may be needed, to list the agreements for each client, then iteratively work backwards through the resulting table to find the earliest qualifying start date. The only consolation to the amount of recursion involved is that the table I'm basing the query on was created via a MakeTable query that filtered the raw Agreements table, so only agreements with an end date greater than [Prompt] - 365 days or null are included, and the Agreements table this is running off is under 10,000 records.
Related
I currently have a table which holds rate periods for services. These periods need to be created in the following way based on a provided start date and end date
If start date is not the start of a week, a record must be inserted
from the Start date until the end of the week containing the start
date.
The next record to be inserted will be the start of the week after the start date up until the end date of the last full date prior to the end date (it can be up until the end date, if the end date is a last day of the week.
There is also a requirement to add individual records for bank holidays
The table is currently populated using recursive stored procedures,but has been failing recently due to exceeding the max nest level for SP', functions etc.
I want to remove this issue and I have no issues creating the table where there are no bank holidays, but I am having problems dealing with the bank holiday insertion and update of previous rates entered.
For example take the following
Start Date: 5th Jan 2017
End Date: 8th April 2017
Last Day of Week: Sunday
Bank Holidays: Mar 9th and Apr 6th
The returned records should be
5th Jan - 8th Jan (5th is not a Monday)
9th Jan - 5th Mar (End week prior to Bank Holiday)
6th Mar - 8th Mar (part week due to Bank Holiday)
9th Mar - 9th Mar (Bank Holiday)
10th Mar - 12th Mar (Part week due to Bank Holiday)
13th Mar - 2nd Apr (Full weeks)
3rd Apr - 5th Apr (Part week due to Bank Holiday)
6th Apr - 6th Apr (Bank Holiday)
7th Apr - 8th Apr (End of Period)
I have looked into using recursive CTE's to do this but I am having issues with this.
Any ideas on the best way to implement the above?
I have two files, one with event date, the other one is the security prices I need to match the month with event month 0, -1 (previous month), and +1 (the month after event month). So e.g., one observation has event date 1/1/2010, I have the daily bond prices from 1/1/2009 to 1/20/2010, but I need to match January,2010 to December 2009 prices and February 2010. I have the following codes to do that,
PROC SQL;
CREATE TABLE test AS
select *
FROM bondprice as a, sdc as b
where b.Participant_CUSIP=a.cusip
& INTCK('MONTH',b.Alliance_Date,a.time)>=-1
& INTCK('MONTH',b.Alliance_Date,a.time)<=1 ;
QUIT;
DATA test1;
SET test;
BY deal_number CUSIP code time;
IF first.code THEN price1=price;
IF first.code THEN day1=time;
IF last.code THEN price0=price;
IF last.code THEN day0=time;
RUN;
clearly this observation should be only matched in 1-month Jan 2010 (0,0) and 2-month Dec 2009 to Jan 2010 (-1,0), because it does not have 3-month Feb 2010's prices. However, if using my codes above, it will yield as a valid obs who has 3-month price since it fell into the range of >=-1 and <=1.
So the first part of code is not accurate (the >= and <= range): it yields any prices that falls into December 2009 to Feb 2010, this is wrong because of two situations. First, if the bond prices stops in between Dec 2009 and Jan 2010, it will be counting as a valid 2-month and 3-month observations. Second, if the bond prices begins in between Jan 2010 and Feb 2010, it will be counting as a valid 3-month observation. Both of these two situation will yield invalid observations, since the first situation do not have Feb 2010 prices but still counts as 2-month and 3-month, and the second situation do not have either Dec 2009 or Jan 2010 prices, but still counts as 3-month.
Will someone help me with this? How can I modify the code so that the 3-month window and 2-month window contains the relative months?
I hope I describe the problem clearly. Please let me know if anything is unclear.
I've uploaded an example to this problem here.
https://www.dropbox.com/s/hx9ahst7nts4k0q/ex1.xlsx?dl=0
I would like to get a running tally of how many widgets were/are rented at any one time, by month, by year. Data is held in an MS Access 2003 db;
Table name: rent_table
Fields:
rentid
startdate
enddate
rentfee
rentcost
bookingfee
Something like; Count number of rentid's that fall between month/year, then group them?
e.g. if a widget was rented from 5th Jan 2014 to 8th April 2014 it would appear as a count in Jan, Feb, Mar and April tally's.
Many thanks.
EDIT
More details (sorry);
Access db is fronted by classic ASP.
If possible I don't want to create any new tables.
No input is required in order to run the report.
There are around 350-400 widgets that could be rented at any one time.
Each widget is rented exclusively.
Report output example;
Month | Year | NumRented
Jan 2014 86
Feb 2014 113
...
Can a query pick up dates within dates? So literally do a count of the table where date >Dec 31st 2013 AND <1st Feb 2014 (to grab a count for all of January 2014) and would that include the example of the rent starting on the 5th Jan? So I could just do twelve counts for each year?
create a calendar table, e.g.
table = cal_yyyymm with one column dt_yyyymm as numeric field
populate the table with ... say 5 or 10 years of data
201401 201402 201403 ... 60 or 120 rows, a small table
make a sql
Select
dt_yyyymm,
count(*) as cnt
From cal_yyyymm
Left Join rent_table
On format(startdate,"yyyymm") >= dt_yyyymm
And dt_yyyymm >= format(enddate,"yyyymm")
think about the complications in the data -- --
widget was rented from 5th Jan 2014 to 8th Jan 2014
and again rented from 11th Jan 2014 to 21st Jan 2014
does this count at 1 or 2 in the month?
if it is 1, then the sql gets more complicated because
the rent_table first needs to have its dates converted
to yyyymm format, and second needs to be de-duped on rentid,
and third then joined to cal_ On the dates...
Please help.
We have two tables. A list of accounts and the other is a change log. I need to add a new column in table 1 where the value is the amount in table 2 for the correct account and correct validity period.
ex.
table 1:
account# beginning period ending period
1 January 1, 2012 January 31, 2012
2 January 12, 2012 February 12, 2012
table 2:
account # amount valid period beg valid period end
1 10 january 1, 2009 december 5, 2010
1 20 december 6, 2010 june 1, 2011
1 30 june 2, 2011 december 1, 2012
2 13 january 15, 2011 december 15, 2011
2 20 december 16, 2011 february 20, 2012
Thanks.
Although it is a bit complex requirement it could be done with built-in functions (although it can look a bit obscure :-) ). Specifically I mean function SUMIFS.
It has several parameters.
The first one is an area with values to be summed. It is B8:B12 in this example.
The second is an area whith values to be checked with some condition. It is A8:A12.
The third is a criterion to be applied for area from second parameter. It is (inter alia) account #.
So the formula says: sum all values from rows in B8:B12 where account # (A8:A12) is equal to desired account # (e.g. A3).
Ok, it is not all, you need specify the time range. It would be a bit clunky because you must check if two time period are overlapping (it would be easier to check if one date is in specified period).
But it could be done because SUMIFS can take another pairs of criteria range and criterion. But it cannot be used for OR condition, so you had to combine more SUMIFS.
Nice article about overlapping ranges is e.g. http://chandoo.org/wp/2010/06/01/date-overlap-formulas/
BTW: you have to format cells in B2:C3 and C8:D12 as a date to be able to compare them.
The clock on the gym wall also shows the day name and the day of the month. This morning it showed Tuesday - 23.
The day obviously rotates through a cycle of 7 - and showed "Tuesday" correctly. The day of the month, though, presumably rotates through a cycle of 31 and showed "23" incorrectly - today is the 1st December (ie. not the 31st November). So this error has been slowly accruing over time.
Given the assumption that no-one has ever reset the clock, what's the most elegant, quick, optimised way of suggesting some of the possible dates for when this clock was bought brand new.
(Bonus credit for showing when the clock will again show the correct day/number combination.)
01-Oct-17 is when the clock will again show the correct day/number combination.
The day of the week (i.e. Tuesday, ... etc) will always be correct, so it is irrelevant to your problem.
Assuming non leap year, you can build a table of 12 rows (1 per month) containing the number of days in this month minus 31.
Jan 0
Feb -3
Mar 0
Apr -1
May 0
Jun -1
Jul 0
Aug 0
Sep -1
Oct 0
Nov -1
Dec 0
You can build a table of the displayed date for every 1st of the month, by adding to the day of the previous month the related number in this list. If the number is negative or equal to zero, add 31 to the figure.
i.e. from the 1st Dec 09 (date at which the clock is displaying 23), you can go to the 1st Jan 10.
You look at this table and find the figure next to Dec, it is 0.
Add 0 to 23 and you know that on the 1st Jan 10, the clock will be displaying 23.
From the 1st Jan 09, you know that the date which will be displayed on the 1st Feb 10 is 23.
From the 1st Feb 10, you can compute the value for the 01 Mar 10, it is 23 + (-3) = 20.
... etc
So, now, at every start of month where you get a value of 1 in this table, you know that the dates in this month will be correct.
If you have to include leap year, you need a second table with the values for a leap year or make an exception for February.
If you want to use this computation for previous dates, substract the figure from the table and when the number you obtain is over 31, just substract 31 to get the day number.
Using these tables and taking in account leap years.
The last past date at which the clock was correct was the 30 September 08 (it was correct between the 01-Jul-08 and the 30-Sep-08)
The next date at which it will be correct will be the: 01-Oct-17 and it will still be correct on the 30-Nov-17.
Now = 1 Dec 2009.
1st day of the month minus 23rd of past month = 8 days (assuming 31 day month).
Moving back counting non-31-days month...
Nov, Sep, June, Apr, Feb (X3), Nov = 8 days offset
So it was bought before Nov 2008?
I didn't code a single line for it, so pardon me if the answer is way off.
In Excel, you can test any date in A2 to see whether the clock will be correct on that date, with the formula =MOD(A2+19,31)+1=DAY(A2)