How to get timestamp to a specific day in 2 weeks - mysql

I am struggling abit to figure out how to set invoices raised on a specific timestamp to a friday two weeks in the future. This is an example data of how I would like each transaction to be set to be paid 2 weeks in the future on a Friday. I have some invoices that need to be set on a Thursday too. How would I go about to take the timestamp of each invoices raised in the week, to have a date set 2 weeks friday? or Thursday?
I tried this which works at setting the date as the Friday in 2 weeks, but goes wrong because it starts the week on a Sunday instead of Friday
DATE_ADD(timestamp, INTERVAL (25 - WEEKDAY(timestamp)) DAY) AS pd
Timestamp Due date
2015-01-01 2015-01-22
2015-01-02 2015-01-22
2015-01-03 2015-01-22
2015-01-04 2015-01-22
2015-01-05 2015-01-22
2015-01-06 2015-01-22
2015-01-07 2015-01-22
2015-01-08 2015-01-29
2015-01-09 2015-01-29
2015-01-10 2015-01-29
2015-01-11 2015-01-29
2015-01-12 2015-01-29
2015-01-13 2015-01-29
2015-01-14 2015-01-29

Using
DATE_ADD(DATE_ADD( <<your_date_here>> , INTERVAL 2 WEEK),INTERVAL (6-DAYOFWEEK(<<your_date_here>>)) DAY)
should do the trick( if what you want is your_date + 2 weeks and next friday from that ).
If what you want is 2 fridays into the future it should be:
DATE_ADD(DATE_ADD( <<your_date_here>>,INTERVAL (6-DAYOFWEEK(<<your_date_here>>)) DAY) , INTERVAL 2 WEEK)
Did this do the trick for you?
Later edit:
SELECT DATE_ADD( DATE_ADD( '<<your date here>>', INTERVAL IF(DAYOFWEEK('<<your date here>>') > 5 ,16 , 14) DAY ), INTERVAL 6 - DAYOFWEEK( DATE_ADD( '<<your date here>>', INTERVAL IF(DAYOFWEEK('<<your date here>>')>5,16,14) DAY )) DAY );
I explain :
DATE_ADD( '<< your date here>>', INTERVAL IF(DAYOFWEEK('<< your date here>>') >5 ,16 , 14)
You add 14 days if the day of week is from Sunday to Thursday and 16 days if it is Friday or Saturday( in order to force it into the next week.
Now to this you again add the number of days necessary to reach Friday.
The example in your original question is wrong:
The 1st of January 2015 was in a Thursday so you add 14 days( 15 Jan 2015) + 1 so you reach Friday(16 Jan 2015).
2nd Jan 2015 was a Friday but, according to your wishes, you consider Friday the beginning of the work-week so you're looking for the 3rd Friday into the future( 23 Jan 2015 ).
3rd Jan 2015 -> 23rd Jan 2015
4th Jan 2015 -> 23rd Jan 2015
.
.
.
8th Jan 2015 -> 23rd Jan 2015
9th Jan 2015 -> 30th Jan 2015
10th Jan 2015 -> 30th Jan 2015
...
and so on and so forth.

Related

MySQL Get data by previous quarter

I am trying to find the last entry for the previous years quarter.
All I can access is year i.e 2021 and quarter i.e 1
Here is the data in my database:
id
name
start
end
16
April 2021
2021-04-01
2021-04-30
15
March 2021
2021-03-01
2021-03-31
14
February 2021
2021-02-01
2021-02-28
57
November 2020
2020-11-01
2020-11-30
55
October 2020
2020-10-01
2020-10-31
29
September 2020
2020-09-01
2020-09-30
27
July 2020
2020-07-01
2020-07-31
24
April 2020
2020-04-01
2020-04-30
23
March 2020
2020-03-01
2020-03-31
22
February 2020
2020-02-01
2020-02-29
21
January 2020
2020-01-01
2020-01-31
Using the MySQL quarter function I can get it to print out the quarter as an integer in another column:
SET #given_year = 2021;
SET #given_quarter = 1;
SELECT
id, name, start, end, QUARTER(end) as "Q"
FROM
submissions
id
name
start
end
Q
16
April 2021
2021-04-01
2021-04-30
2
15
March 2021
2021-03-01
2021-03-31
1
14
February 2021
2021-02-01
2021-02-28
1
57
November 2020
2020-11-01
2020-11-30
4
55
October 2020
2020-10-01
2020-10-31
4
29
September 2020
2020-09-01
2020-09-30
3
27
July 2020
2020-07-01
2020-07-31
3
24
April 2020
2020-04-01
2020-04-30
2
23
March 2020
2020-03-01
2020-03-31
1
22
February 2020
2020-02-01
2020-02-29
1
21
January 2020
2020-01-01
2020-01-31
1
I tried using WHERE and LIKE but it is returning 0 rows:
SELECT * FROM (
SELECT
id, name, start, end, QUARTER(end) as "Q"
FROM
submissions as s
) AS vs
WHERE
vs.end
LIKE
#given_year
AND
vs.Q < #given_quarter
I also need to account for the possibility that there may be no rows this year and I need to find the previous year.
For example with these two rows, if I was passed the year 2021 and quarter 1 I would need to return November of the previous year and a different quarter.
id
name
start
end
Q
14
February
2021
2021-02-01
2021-02-28
57
November
2020
2020-11-01
2020-11-30
If I understand correctly, you want all the rows from the quarter in the data before a given quarter. You can filter and use dense_rank():
select s.*
from (select s.*,
dense_rank() over (order by year(start) desc, quarter(start) desc) as seqnum
from submissions s
where year(start) < #given_year or
(year(start) = #given_year and quarter(start) < #given_quarter)
) s
where seqnum = 1;
The above returns all rows from the previous quarter (which is what I thought you wanted). If you want only one row:
select s.*
from submissions s
where year(start) < #given_year or
(year(start) = #given_year and quarter(start) < #given_quarter)
order by start desc
limit 1;

How to compare Month-to-Date to previous Month-to-Date using 'Week Ending' date?

Current SQL Code:
SUM(CASE WHEN MONTH(`Week Ending`) = MONTH(`Week Ending`) - 1
THEN Dollar_Amt
ELSE 0
END) AS Dollar_Amt_2
Sample Table:
Week Ending Max_Dt Dollar_Amt
2016-09-03 2016-09-01 10
2016-09-10 2016-09-01 15
2016-09-17 2016-09-01 5
2016-09-24 2016-09-01 30
2016-10-01 2016-10-01 5
2016-10-08 2016-10-01 15
2016-10-15 2016-10-01 10
The issue I have is that the previous month is always greater than the current month because the previous month is complete and therefore has more Week Ending dates.
I want to compare current Month-to-Date to the previous Month-to-Date, but I am having trouble accomplishing this using dates aggregated at the weekly (Week Ending) level. Any help would be much appreciated.

MYSQL employee working hours for each day in date range

Hi I have a MySQL query that looks into a table that holds hours for each day the employee work. My query looks at the day of the date and the result is what hours we worked. so let say 2015-11-24 is Tuesday then 8.
How do I run the query without PHP to look at every day in a date range?
Thanks
Eg. $holidaystart = '2015-11-24';
$holidayend = '2015-11-30';
#Table employees hours id Mon Tue Wed Thu Fri Sat Sun
1 8 8 0 8 8 8 0
$sql= "select empId,
'".$holidayStart."' as date,
case dayname('".$holidayStart."')
when 'Sunday' then Sun
when 'Monday' then Mon
when 'Tuesday' then Tue
when 'Wednesday' then Wed
when 'Thursday' then Thu
when 'Friday' then Fri
when 'Saturday' then Sat
else 0 end as hours
from employees" ;
Edit
I have one table that holds employee id number (empId) Then each day of the week Mon, Tue, Wed, Thu, Fri, Sat, Sun
--------------------------------------------------------------
| empid | Mon | Tue | Wed | Thu | Fri | Sat | Sun |
--------------------------------------------------------------
| 1 | 8 | 8 | 0 | 8 | 8 | 8 | 0 |
| 2 0 8 | 8 0 | 8 | 8 | 8 |
--------------------------------------------------------------
so employee 1 as a working shift of 8 hour on Mon, 8 on Tue, 0 Wed, 8 Thu, 8 Fri, 8 Sat 0 Sunday . So what I am trying to achieve is to look at lets say 2015-11-24 to 2015-11- 26 and see how many hours are employee 1 will work between the 2 date based on how many hours they are suppose to work in each day Mon = 8 hour shift Tue = 8 hour shift Wed = 0 (day off) Thu = 8 Fri = 8 Sat = 8 Sun day off
FIDDLE DEMO
As you can see by the demo 2015-10-10 is saturday so empId 1 = 8 hours empId 2 = 6 hours and empId 3 = 8 hours so how do i do this using a date range?
Assuming your table has the following columns:
empId - Employee id
workDate - the date they worked
hoursWorked - the number of hours they worked that day
Then something like this
SELECT empId
SUM(IF(dayname(workDate) = 'Sunday', hoursWorked, 0)) As Sun,
SUM(IF(dayname(workDate) = 'Monday', hoursWorked, 0)) As Mon,
SUM(IF(dayname(workDate) = 'Tuesday', hoursWorked, 0)) As Tues,
SUM(IF(dayname(workDate) = 'Wednesday', hoursWorked, 0)) As Wed,
SUM(IF(dayname(workDate) = 'Thursday', hoursWorked, 0)) As Thurs,
SUM(IF(dayname(workDate) = 'Friday', hoursWorked, 0)) As Fri,
SUM(IF(dayname(workDate) = 'Saturday', hoursWorked, 0)) As Sat,
FROM employees
GROUP BY empId
WHERE workDate BETWEEN :startDate AND :endDate
Don't forget to use prepared statements to protect yourself from SQL injection!
Ok, so this is a blind shot, because you haven't provided us with the structure of table employees. Try to following:
$sql = mysql_query('SELECT * FROM employees WHERE `date` BETWEEN ".$startDate.'" AND "'.$endDate.'"');
while($row=mysql_fetch_assoc($sql)){
$arr[$row[date]]=$row;
}
$totalHours=0;
for($i=strtotime($startDate);$i<=strtotime($endDate);$i+=86400){
$day=$arr[date('Y-m-d H:i:s',$i];
if($day){
$id=$day[id];
}
$hours=($day)? $day[hours] : 0;
$totalHours+=$hours;
echo "Employee $id Day ".date('D',$i). " Hours $hours";
}
echo "Total hours $totalHours";
You shouldn't use the mysql library and instead use mysqli or PDO.
Try this dynamic Pivot query:
SET #sql = NULL;
SELECT empId,
GROUP_CONCAT(DISTINCT
CONCAT(case dayname(table_date_field)
when 'Sunday' then Sun
when 'Monday' then Mon
when 'Tuesday' then Tue
when 'Wednesday' then Wed
when 'Thursday' then Thu
when 'Friday' then Fri
when 'Saturday' then Sat
else 0 end as hours
)
) INTO #sql
FROM employees;
SET #sql = CONCAT('SELECT empId,', #sql, ' FROM employees GROUP BY empId');

mysql list data excluding weekends

I have table with id (PK,AI), name and date, when users register I set date = CURDATE().
I have a PHP page where I have to list the names where CURDATE() >= (date + 3 days) excluding weekends (Sat and Sunday) means I list names of users who completed the registration before 3 days but I don't count weekends.
which means if someone register on Monday, he should listed on the page on Thursday and if he registered on Friday, the page list him only on Wednesday (excluded weekends)
Is there any method in MySQL to accomplish this ?
Instead of doing a complex mysql query, could you not just pass in a different date to check against, depending on the weekday from your php script?
So, instead of comparing in your sql query your date+3days <= today, pass in a variable for the date offset or just calculate the date in php and pass the date in.
day of the week | offset
1 | 5
2 | 5
3 | 5
4 | 3
5 | 3
6 | 4
7 | 5
Easy in MySQL.
SELECT CURRENT_DATE + interval (3 + 2*(weekday(CURRENt_DATE) > 1)) day;
Thanks to #JamesBlond for the table, saves me to explain. ;-)
EDIT: I was confused by the (index-killing) way to request data: normally you should try taking the date from the table unmodified and to fiddle with your CURRENT_DATE data.
As long as I understand you right, it should be the following, so you also could simply use a CASE WHEN clasue, that is more readable and easier to adopt.
thedate - interval (
3 + 2*(weekday(thedate) < 3)
+ (weekday(thedate) > 4) * (weekday(thedate)-4)) DAY
AS 3_days_before
http://www.sqlfiddle.com/#!2/49731/9/0
THEDATE WEEKDAY(THEDATE) THEDATE_FORMATTED 3_DAYS_BEFORE FORMATTED_3_DAYS_BEFORE
April, 27 2014 00:00:00+0000 6 Sunday April, 22 2014 00:00:00+0000 Tuesday
April, 28 2014 00:00:00+0000 0 Monday April, 23 2014 00:00:00+0000 Wednesday
April, 29 2014 00:00:00+0000 1 Tuesday April, 24 2014 00:00:00+0000 Thursday
April, 30 2014 00:00:00+0000 2 Wednesday April, 25 2014 00:00:00+0000 Friday
May, 01 2014 00:00:00+0000 3 Thursday April, 28 2014 00:00:00+0000 Monday
May, 02 2014 00:00:00+0000 4 Friday April, 29 2014 00:00:00+0000 Tuesday
May, 03 2014 00:00:00+0000 5 Saturday April, 29 2014 00:00:00+0000 Tuesday
May, 04 2014 00:00:00+0000 6 Sunday April, 29 2014 00:00:00+0000 Tuesday
May, 05 2014 00:00:00+0000 0 Monday April, 30 2014 00:00:00+0000 Wednesday
May, 06 2014 00:00:00+0000 1 Tuesday May, 01 2014 00:00:00+0000 Thursday
May, 07 2014 00:00:00+0000 2 Wednesday May, 02 2014 00:00:00+0000 Friday

To display missing values [date] as range from Date Column

I have output as below
ID Date
Null 2012-10-01
1 2012-10-02
2 2012-10-03
NULL 2012-10-04
3 2012-10-05
NULL 2012-10-06
4 2012-10-07
NULL 2012-10-08
5 2012-10-10
NULL 2012-10-11
NULL 2012-10-12
6 2012-10-13
NULL 2012-10-16
As it has missing dates with value as NULL. I need to show final output as
2012-10-01 - 2012-10-01 (1 day )
2012-10-04 - 2012-10-04(1 day )
2012-10-06 - 2012-10-06(1 day )
2012-10-08 - 2012-10-08(1 day )
2012-10-11 - 2012-10-12(2 day )
2012-10-14 - 2012-10-14(1 day )
You can generate the date ranges using the following query:
select
min(date) as start,
max(date) as end,
datediff(max(date), min(date)) + 1 as numDays
from
(select #curRow := #curRow + 1 AS row_number, id, date
from Table1 join (SELECT #curRow := 0) r where ID is null) T
group by
datediff(date, '2012-10-01 00:00:00') - row_number;
The logic is based on a clever trick for grouping consecutive ranges. First, we filter and number the rows in the subquery. Then, the rows that are grouped together are found by comparing the number of days after 2012-10-01 to the row number. If any rows share this value, then they must be consecutive, otherwise there would be a "jump" between two rows and the expression datediff(date, '2012-10-01 00:00:00') - row_number would no longer match.
Sample output (DEMO):
START END NUMDAYS
October, 01 2012 00:00:00+0000 October, 01 2012 00:00:00+0000 1
October, 04 2012 00:00:00+0000 October, 04 2012 00:00:00+0000 1
October, 06 2012 00:00:00+0000 October, 06 2012 00:00:00+0000 1
October, 08 2012 00:00:00+0000 October, 08 2012 00:00:00+0000 1
October, 11 2012 00:00:00+0000 October, 12 2012 00:00:00+0000 2
October, 16 2012 00:00:00+0000 October, 16 2012 00:00:00+0000 1
From there I think it should be pretty trivial for you to get the exact output you are looking for.