In my app users save a report each Friday for an organization. All my records in the reports table hold organization_id, day and workdays.
I want to get the sum of all workdays at the last Friday of each month.
With the following line I am able to select all reports for organization #8 and sum workdays for each Friday:
#all_report_sums = Report.where(:organization_id => 8).group(:day).select("day, SUM(workdays) AS sum_workdays")
The result:
[{"id":null,"day":"2017-02-03","sum_workdays":3},{"id":null,"day":"2017-02-24","sum_workdays":33},{"id":null,"day":"2017-04-07","sum_workdays":12}]
However in my output I only want the maximum dates of each month (which is the last Friday of each month) - so in my case this would be 2017-02-24 and 2017-04-07.
How can I achieve that?
This is what are you looking for
How to get the latest record from each group in ActiveRecord?
User.group(:user_id).having('day = MAX(day)')
Related
I am developing an automated calendar for a school on AirTable, but I am struggling to add if there is a bank holiday between the start date and end date. If the bank holiday falls on a weekday, it needs to add +1 day to the end date.
I have created a "bank holiday" table, as well as a full calendar table (containing everyday of the year and what weekday it falls on).
I'd like for the user to have the end date generated automatically by only writing the start date.
For example:
I have a session starting on Monday, 7th of march. The "session type" would be "Course 1", which has a duration of 10 days (two weeks, monday to friday - I don't know if the duration should be 14 days instead?). If there's a bank holiday in the 10 days after the start date, and it's on a weekday, it needs to add +1 to the end date. If the end date falls on a sunday, it needs to add +2 so that it ends on a Monday.
The course is divided in multiple classes, it would also be awesome to have a timeline view with the full Course and all the classes.
Here are some screenshots of my tables :
I know there is a possibility to write a script in Python with an AirTable API... but is there an easier way ?
I've dealt with a problem like this before: when an event happened in relation to other events mattered.
You'd think by the use of the words "in relation" that you could deal with this in a relational way, but I see it as a rule:
If Event A happens at Time 1, and it's so much or so little time from Event B, then do with Event A...
And, again by my way of thinking, rules are expressed in code.
And if you actually even can express that with a relation, I think it'd be very convoluted.
So, for your problem, you need to encode every schedule-able day that's 10 working days or less before a Bank Holiday (BH) so that if the day is selected you know it's less than 10 days from a BH and can conditionally add another day to the end date.
I looked at your examples, and here's my solution. I have a Calendar table which has all days, and two supporting "Bank Holiday" fields: does the date fall on a BH, and if not, is the date 10 days or less from a BH. We're looking at my All view, here:
I also have the view, Weekday, not bank holiday, and that's the view that you can pick a day from to schedule an event from the Event table.
The Event table:
You pick a day from the Start day field. Start day < 10 work days to Bank holiday? is a lookup field from the Calendar table for that day. End day is this formula:
DATETIME_FORMAT(
DATEADD(
{Start date},
IF(
{Start day < 10 work days to Bank holiday?},
14,
13),
'day'),
'ddd, MMM Do')
I am working on a weekly budget sheet and I would like to show dates for each upcoming friday for the current month. How can I do this?
You may apply sequence formula to generate a serial of number for each Friday day and to return all the subsequence date for your budgeting:
=arrayformula(date(year(A1),month(A1),
SEQUENCE(ROUNDUP(DATEDIF(A1,EOMONTH(A1,0),"D")/7,0)-1,1,DAY(A1)+7,7)))
So how does it work:
date(year, month, day)
Return a new date from the number given by formula
ROUNDUP(DATEDIF(A1,EOMONTH(A1,0),"D")/7,0)-1
To calculate to total number of remaining week between the current date and end of the month, you can use Rounddown but need take remove minus 1 at the back
DAY(A1)+7
Return the day of next Friday based on the current Friday date
SEQUENCE(row,column,start,steps)
The row value will determine how many counts of value to be populated, which is the number of week from above formula, start will be start date of next Friday, and step is every 7 days
Sample Sheet:
Remark:
You can add the if statement to return blank when the number of remaining week is 0 to prevent the formula return error
if((ROUNDUP(DATEDIF(A1,EOMONTH(A1,0),"D")/7,0)-1)=0,""
I am trying to observe historical trends on customer acquisitions (new and returning) and am looking to use a formula to automate it for me.
Essentially, I am looking to determine the average amount of new customers we acquire on a specific day, specific week, and specific month. For example: what are the average customers we have acquired every Monday for the past 6 months, or what is the average number of customers we acquire the first week of every month?
Solution:
You can use the date operators in your QUERY statement to filter by month, week, or even day of week.
Examples:
every Monday for past 6 months
=query(A1:B, "select avg(B) where datediff(todate(now()),todate(A)) < 180 and dayofweek(A) = 2", 1)
first week of every month
=query(A1:B, "select month(A),avg(B) where day(A) <= 7 group by month(A) offset 1", 1)
You would need to tweak the sample queries to cover your data range and which columns do you need to average and compare.
References:
QUERY()
Query Language Reference | Scalar Functions
I'm trying to iterate over each week in the calendar year and run a query.
range = Date.new(2020,3,16)..Date.new(2020,3,22)
u = User.where(created_at: range).count
But I'd like to do this for EACH week in another range (say since the beginning of this year).
Ruby's Date has a cweek function that gives you the week number but there doesn't seem to be a way to easily get from the week number to the date range.
Anyway, not sure how helpful cweek will be as I need week to run Sunday -> Saturday.
Thoughts?
I'm assuming this is Postgres and the model name is User based on your previous question.
If this blog is to to believed you can shift a date one day to get sun-sat day week.
User.group("(date_trunc('week', created_at::date + 1)::date - 1)")
.count
If you want the to select the actual week number while you are at it you can select raw data from the database instead of using ActiveRecord::Calculations#count which is pretty limited.
class User
# #return [ActiveRecord::Result]
# the raw query results with the columns count, year, week
def self.count_by_biblical_week
connection.select_all(
select(
"count(*) as count",
"date_part('year', created_at)::integer as year",
"(date_part('week', created_at::date + 1) - 1)::integer as week"
).group(:week, :year)
)
end
end
Usage:
results = User.where(created_at: Date.new(2020,3,16)..Date.new(2020,3,22))
.count_by_biblical_week
results.each do |row|
puts [row[:year], row[:week], row[:count]].join(' | ')
end
Adding the year to the group avoids ambiguity if the results span multiple years.
I have a Purchase model and I want to group all of the records by their ordered_datetime field. However, I don't care about the time, I just want to group by the date. So if there are 2 orders ordered on:
5/12/2014 12:00PM
5/12/2014 3:00PM
They should be grouped together even though they happened at different times during the day.
Is there a way to do this? Purchase.uniq.pluck(:ordered_datetime) separates the 2 records into 2 groups since their times are different.
You can use the DATE function on the timestamp column:
Purchase.group('DATE(ordered_datetime)').count
Which returns each date with a purchase count.
You can also sort the dates by adding an order clause:
Purchase.group('DATE(ordered_datetime)').order('date_ordered_datetime').count