Help with some dimensional data formulas - mysql

I have most of my datetime dimensions defined but having trouble with these. Have 0 idea how to implement these in mysql for creating my datetime dimensions.
Minute of day - 1440 minutes span.
Day per Bi-weekly - 14 days span - from 1st week of year, starting at 1st day of year.
Day per quarter - 4 quarters per year, so within those quarters need day count like 1st day of quarter, 2nd day, etc.
Week per quarter - Same like day per quarter but at the week level.
One way i can slve these is by using CASE statements for each time interval but that is too much, like (if hour = xx & minute = xx then minuteOFDay = xxxx). Same for the other data but I am sure there must be a 1-2 line formula to get these instead?

For the "minute of day", you can use this (assuming that you have your data as DATETIME named eventdt):
SELECT (HOUR(`eventdt`) * 60) + MINUTE(`eventdt`)
AS minute_of_day FROM `your_table`
For "day per bi-weekly", day of year modulo 14 might be usable:
SELECT (DAYOFYEAR(`eventdt`) % 14) AS day_per_biweekly
FROM `your_table`

Related

mysql - get max and min values of column grouped by day with 2 hour offset (i.e., 1/19/23 2AM - 1/20/23 2AM), not midnight to midnight

I'm trying to get a max value and min value in a 24 hour period (2AM-2AM) grouped by power meter box identifier (essentially a serial number) in mysql.
I'm beating my head against a wall here. No matter what I try to do when I try grouping by day with an offset of X hours (in this example 2 - and I've tried many of the stack overflow solutions to no avail), it's still grouping from midnight to midnight.
select power_box, max(reading), min(reading)
from meters
GROUP BY
year(date_add(from_unixtime(eventTime/1000), interval -2 hour)),
month(date_add(from_unixtime(eventTime/1000), interval -2 hour)),
day(date_add(from_unixtime(eventTime/1000), interval -2 hour)),
power_box
;
Any SQL experts out there to help?
The grouping is still midnight to midnight - can't figure this out!

How to maintain different values for every hour of day in week

I want to add different rate(cost of hour) for different hours of day from Monday to Sunday in a mysql DB table.
I thought of 2 ways
creating a column of every day(Week day) so that when I fetch a column I will get entire days rate in one column
creating columns for every hour so that I have to fetch based on week day number(1 for Monday 2 for Tuesday). I will get rates of entire day in row
Which is good approach from above 2 or any other good approach for doing this ?
Thanks
Given the available MySQL time functions, WEEKDAY and HOUR are the easiest way to get to the values you need.
So a table like:
CREATE TABLE rate (day TINYINT NOT NULL,
hour TINYINT NOT NULL,
rate FLOAT NOT NULL,
PRIMARY KEY (DAY, HOUR))
So a query could look like:
SELECT rate
FROM rate
WHERE day=WEEKDAY(NOW())
AND hour >= HOUR(NOW())
ORDER BY day, hour LIMIT 1
This >= and ORDER/LIMIT just allows the table to have gaps of hours.

Return all records within 3 month period (MySQL)

So what I want to achieve is to return data from within the last 3 months.
My current MySQL query is as follows:
SELECT MONTH(service_date_time) AS month, SUM(service_price) AS total FROM appointments WHERE user_id = 1 AND service_date_time >= last_day(now()) + INTERVAL 1 day - INTERVAL 3 month GROUP BY YEAR(service_date_time), MONTH(service_date_time)
My table appointments contains data from January and May and service_date_time is a date_time field.
The problem I'm having is that it returns 2 rows, one row totaling the price for January and one row totaling the price for May. The row for May shouldn't be returned since it is not within the past three months.
Anyone have an idea why?
You are requesting all records that are greater than the given date, If you want all the records up to now you'll have to ask for a range for example:
WHERE service_date_time BETWEEN (LAST_DAY(NOW()) + INTERVAL 1 DAY - INTERVAL 3 MONTH) AND NOW()
this would limit the records & give you from 3 months ago till now

specify time period given interval in MySQL

I have the following tables:
In other words I have a set of customers I follow throughout time. I have a column of the date of their first purchase, and another column with another purchase they made at another time.
I want to make a column which specifies the time period in which the specific purchase was made. The time periods should be defined such that a new period starts the 20th each month and the first period for each customer should therefore be the day they made their first purchase and until the 20th.
This is illustrated below:
What I need:
I have tried to implement this via a handful of if statements like:
WHEN DAY(c.created)<21 and DAY(s.created)<21 and year(c.created)-year(s.created)=0
THEN MONTH(c.created)-MONTH(s.created)+1
WHEN DAY(c.created)>20 and DAY(s.created)<21 and year(c.created)-year(s.created)=0
THEN MONTH(c.created)-MONTH(s.created)+2
and so on.
I want to know if there is an easy(er) and simple(r) way to handle this problem?
I work in MySQL Workbench 6.3 CE
The date of the first day of the calendar month in which a customer made a purchase can be found like this:
DATE_FORMAT(First_purchase , '%Y-%m-01')
So, the date of the first day of your fiscal month, which starts on the 20th of each calendar month, can be found like this.
DATE_FORMAT(First_purchase - INTERVAL 19 DAY, '%Y-%m-01') + INTERVAL 19 DAY
Then, you can use TIMESTAMPDIFF as follows to get the number of months between two of these sorts of numbers.
TIMESTAMPDIFF(
MONTH,
DATE_FORMAT(First_purchase - INTERVAL 19 DAY, '%Y-%m-01') + INTERVAL 19 DAY,
DATE_FORMAT(Date_created - INTERVAL 19 DAY, '%Y-%m-01') + INTERVAL 19 DAY) + 1
That will get you the number of the fiscal month, starting with First_purchase, in which Date_created is found, where the first fiscal month has the number 1.
Using native date arithmetic in place of DAY(), MONTH(), and YEAR() functions is much more likely to keep working over ends of years and in leap years and all that.

How to get the count of specific days from week between a date range in mysql?

I have a table "task_table" containing columns-
Task_id, Start_date, End_date
And I have one more "configuration" table which has the records that tell which days of the week are working days.
This table has two columns -
week_day, isHoliday
and this table contains seven records as week_days are the Monday,Tuesday.....Sunday , and each record has an entry as 1 or 0. If a day is a holiday in any organization then there will be 0 against that day. Like if an organisation has holidays on Wednesday and Friday every week then there will be 0 against Wednesday and Friday only.
Now I want to make a SQL query to get the Task_id, Start_date, End_date, and the count of total days consumed on each task. (These days are the days between task start_date and end_date excluding the holiday days as configured in "configuration" table.)
I don't have time to fully answer this question now, but what I would do is:
Get the date as at the start of the Start_date week, and the date as at the end of the End_date week (you can get this by date_adding an amount of days according to the day of the week.
Then you want to date diff them, divide by seven, multiply by two, and remove any that you would have added (e.g. if the start date was Thursday then you'll need to remove one from the result, as you will have counted one for the Wednesday immediately prior.
I'll write the code out tomorrow (it's late here - something like 14 hours from now or so.) if noone else has suggested a better answer.
Edit: Right, didn't properly read the question, but the tactic still applies with a little fiddling. Speaking of which, here is the fiddle of my solution.
It boils down to the following code:
set #holidaysPerWeek = (select sum(isHoliday) from configuration);
select
Task_id,
((dateDiff(
DATE_ADD(End_Date, INTERVAL 7 - DayOfWeek(End_Date) DAY),
DATE_ADD(Start_Date, INTERVAL -DayOfWeek(Start_Date) + 1 Day)) + 1) / 7)
* #holidaysPerWeek
- (select sum(isHoliday) from configuration where week_day > DayOfWeek(End_Date))
- (select sum(isHoliday) from configuration where week_day < DayOfWeek(Start_Date)),
DayOfWeek(End_Date)
from task_table
This does exactly what I was saying before, but with a variable number of "weekends" spread throughout the week, by first selecting the number of holidays for if the full weeks were covered, then removing holidays that were before or after the start and end dates respectively.