how to group by week start from friday - mysql

I have table sql like this:
This my query for count tgl:
SELECT count( tgl ) AS total, absen.id
FROM absen
WHERE absen.status = 'm'
GROUP BY absen.id
So I want group by absen.id and absen.tgl
How to group by week from Friday to Thursday?
2016-01-08 is friday and 2016-01-15 is thursday.

Bellow query can bring the result you want, but i think you defined the wrong end date, because in your example from 2015-01-08 up to 2015-01-15 its 8 day and one week has 7 days.
select
count( tgl ) AS total,
absen.id,
CASE WHEN (weekday(tgl)<=3) THEN date(tgl + INTERVAL (3-weekday(tgl)) DAY)
ELSE date(tgl + INTERVAL (3+7-weekday(tgl)) DAY)
END as week_days
FROM absen
WHERE status = 'm'
GROUP BY id,week_days
here is the fiddle fiddle
Query Description:
mysql weekday array numbers:
$weekArr = array(
'Monday' => 0,
'Tuesday' => 1,
'Wednesday' => 2,
'Thursday' => 3,
'Friday' => 4,
'Saturday' => 5,
'Sunday' => 6);
So now suppose today is Tuesday and date is 2016-01-12, now let's count from today towards the start date in our table which is 2016-01-07 and it match with Thursday of past week, so according to the weekday array number its weekday(2016-01-07) == 3 so it goes to the WHEN part of our query, and query will select something like this CASE WHEN (weekday('2016-01-07') <= 3) THEN date('2016-01-07' + INTERVAL(3-3)) that is equal to SELECT '2016-01-07' and so on for others.

I just found how to get this by trouble shooting on excel by using this WEEK('date' + INTERVAL 3 DAY, 3)

Related

In mysql How to find number of sundays in a month

In mysql how to find number of sundays in month by usnig month in where clause
Ex:
month(log_date)=month(now());
month(log_date) = 12;
output: 5 sundays
Possible way to do it which avoids using any tables. This finds the number of days in the month, and depending on that and what day of the week the last day is then it just returns a value
SELECT CASE DAYOFMONTH(LAST_DAY(NOW()))
WHEN 31 THEN
CASE DAYOFWEEK(LAST_DAY(NOW()))
WHEN 1 THEN 5
WHEN 2 THEN 5
WHEN 3 THEN 5
ELSE 4
END
WHEN 30 THEN
CASE DAYOFWEEK(LAST_DAY(NOW()))
WHEN 1 THEN 5
WHEN 2 THEN 5
ELSE 4
END
WHEN 29 THEN
CASE DAYOFWEEK(LAST_DAY(NOW()))
WHEN 1 THEN 5
ELSE 4
END
ELSE 4
END
SQL query for get total sunday in given month from DB
USE BETWEEN :- BETWEEN operator selects values within a given range.
Note :- DAYOFWEEK actually returns 1 for Sunday
SELECT count(*) AS total_sunday FROM `table` WHERE DAYOFWEEK(`date`) = 1 BETWEEN '2017-11-01' AND '2017-11-30';
In mysql just copy and paste the query given below. It will give you number of Sundays in current month.
WITH RECURSIVE offdays as(
SELECT
LAST_DAY(CURDATE()-INTERVAL 1 MONTH) + INTERVAL 1 DAY AS `Date`,
DAYNAME(LAST_DAY(CURDATE()-INTERVAL 1 MONTH) + INTERVAL 1 DAY) AS `DayName`
UNION ALL
SELECT `Date` + INTERVAL 1 DAY, DAYNAME(`Date` + INTERVAL 1 DAY)
FROM offdays WHERE `DATE` < LAST_DAY(CURDATE())
) SELECT count(*) FROM offdays where DAYNAME(DATE) = 'Sunday';
you will get number of sundays in current month. Just replace the CURDATE() with any date. The query will give you the number of Sundays of the month of the date supplied.
Try this function, you use like
count_days_in_month($date_month,$day_idx);
$day_idx is 1 - 7 where Sunday is 1, Saturday is 7
eg.
select count_days_in_month('2020-02-01',1);
delimiter //
create or replace function count_days_in_month(input_date DATE,dayindex INT)
returns INT
DETERMINISTIC
BEGIN
declare start_day_idx INT default (select dayofweek( date_sub(input_date,INTERVAL (DAYOFMONTH(input_date)-1) DAY )) from dual);
declare days_in_month INT default (SELECT dayofmonth(LAST_DAY(input_date)));
declare days_over_28 INT default (days_in_month-28);
if days_in_month > 28 then
if (days_over_28 > (dayindex-start_day_idx)) and ((dayindex-start_day_idx) >= 0) then
return 5;
else
return 4;
end if;
else
return 4;
end if;
END//
Eg to test the count of all days in a month:
select
count_days_in_month('2020-02-01',1) 'Sun',
count_days_in_month('2020-02-01',2) 'Mon',
count_days_in_month('2020-02-01',3) 'Tue',
count_days_in_month('2020-02-01',4) 'Wed',
count_days_in_month('2020-02-01',5) 'Thur',
count_days_in_month('2020-02-01',6) 'Fri',
count_days_in_month('2020-02-01',7) 'Sat'
from
dual;//

Prioritizing case in mysql

I want to prioritize the status part. Everything which is not repported should appear first. Regardless date. But now, It orders eveything after date. How can I prioritize the first case 'not repported part'? The rest of the list should appear after date.
SELECT * FROM list
ORDER BY date DESC,
CASE
WHEN `bookings`.`status` = 'Not repported' THEN 1
WHEN day= 'Monday' THEN 2
WHEN day= 'Tuesday' THEN 3
WHEN day= 'Wednesday' THEN 4
WHEN day= 'Thursdau' THEN 5
WHEN day= 'Friday' THEN 6
WHEN day= 'Saturday' THEN 7 WHEN
day= 'Sunday' THEN 8 END ASC
limit 1,20 ";
I want something like this.
------------------------------
DATE----DAY-------STATUS------
2011---Monday-----Not reported
2015---Sunday-----Not reported
2010---Wednedday--Not reported
2016---Monday---------Reported
2015---Monday---------Reported
2014---Tuesday--------Reported
2013---Sunday---------Reported
------------------------------
You have two order statements. One for the date, and one for your booking status. Mysql will first order according to your first order statement, and then according to your second order statement. So switching the order statements solves your problem. In addition there is the "ELSE" keyword for "CASE"s in mysql.
In total I would write it like this:
SELECT *
FROM list
ORDER BY
CASE
WHEN `bookings`.`status` = 'Not repported' THEN 1
ELSE 2
END ASC,
date DESC
LIMIT 1,20
(Im not so sure where your "bookings" table now comes from, but I left it there. You might miss a JOIN clause)
Change the order by
Something like this
SELECT * FROM list
ORDER BY
CASE
WHEN `bookings`.`status` = 'Not repported' THEN 1 ELSE 2
END,
CASE
WHEN day= 'Monday' THEN 2
WHEN day= 'Tuesday' THEN 3
WHEN day= 'Wednesday' THEN 4
WHEN day= 'Thursdau' THEN 5
WHEN day= 'Friday' THEN 6
WHEN day= 'Saturday' THEN 7 WHEN
day= 'Sunday' THEN 8 END ASC,
date DESC
limit 1,20 ";
This will give you this result
'Not repported' , 1/1/2017
'Not repported' , 3/7/2017
'Not repported' , 15/8/2017
Monday , 6/2/2017
Monday , 11/11/2017

Grouping COUNT by Time in MySql

I have a simple query that give me the count of application types; it looks something like this:
SELECT Application_Type, COUNT(*) FROM Loan_Applications GROUP BY Application_Type;
It returns something like this:
Home 3
Car 21
Commercial 16
There is a field in the database called Submission_Date (Of type Date)
How can I query and break up this data by week?
Type This week Last week 2 weeks ago
Home 1 1 1
Car 9 6 6
Commercial 10 0 3
You can try something like:
SELECT
Application_Type,
SUM(IF(Submission_Date BETWEEN CURRENT_DATE AND CURRENT_DATE - INTERVAL 1 WEEK, 1, 0)) AS 'This week',
SUM(IF(Submission_Date BETWEEN CURRENT_DATE- INTERVAL 1 WEEK AND CURRENT_DATE - INTERVAL 2 WEEK, 1, 0)) AS 'Last week',
SUM(IF(Submission_Date BETWEEN CURRENT_DATE- INTERVAL 2 WEEK AND CURRENT_DATE - INTERVAL 3 WEEK, 1, 0)) AS '2 weeks ago',
FROM Loan_Applications
GROUP BY Application_Type
;
Or:
SET #date1w = CURRENT_DATE - INTERVAL 1 WEEK;
SET #date2w = CURRENT_DATE - INTERVAL 2 WEEK;
SET #date3w = CURRENT_DATE - INTERVAL 3 WEEK;
SELECT
Application_Type,
SUM(IF(Submission_Date BETWEEN CURRENT_DATE AND #date1w, 1, 0)) AS 'This week',
SUM(IF(Submission_Date BETWEEN #date1w AND #date2w, 1, 0)) AS 'Last week',
SUM(IF(Submission_Date BETWEEN #date2w AND #date3w, 1, 0)) AS '2 weeks ago',
FROM Loan_Applications
GROUP BY Application_Type
;
You can make a SUMIF type of calculation. The following sums the number of rows where the submission date is within the last week.
SUM(CASE WHEN submission_date >= CURDATE() - 7 THEN 1 ELSE 0 END)
You could then repeat this for different ranges, to get any "bands" that you desire.
Try
SELECT
Application_Type,
SUM(WEEKOFYEAR(Submission_Date) = WEEKOFYEAR(NOW())) AS `This week`,
SUM(WEEKOFYEAR(Submission_Date) = WEEKOFYEAR(DATE_ADD(NOW(),INTERVAL -1 WEEK))) AS `Last week`,
SUM(WEEKOFYEAR(Submission_Date) = WEEKOFYEAR(DATE_ADD(NOW(),INTERVAL -2 WEEK))) AS `2 weeks ago`
FROM Loan_Applications GROUP BY Application_Type;
;
it is based on the fact that SUM of a boolean expression in the group by will count the cases when the expression is true

Last date in quarter MySQL

I have a table with some dates. I need a query which will return the max (last) date from this table and last date of quarter this max date belongs to.
So for data i table
ID| EDATE
--+----------
1|2014-03-06
2|2014-10-12
this query should return 2014-10-12 and 2014-12-31.
As I understand you want the last day of the quarter, so 31 March, 30 June, 30 Sept, 31 Dec? So you can use the answer from Gordon Linoff and adjust it to do that.
You only need a case statement on month(date) and concat that with the year.
http://dev.mysql.com/doc/refman/5.1/de/control-flow-functions.html
str_to_date(
concat(
year(edate),
(case
when month(edate) in (1, 2, 3) then '-03-31'
when month(edate) in (4, 5, 6) then '-06-30'
when month(edate) in (7, 8, 9) then '-09-30'
else '-12-31'
end)
),
'%Y-%m-%d'
)
Getting the day of the last quarter for the date is a bit yucky, but possible. Here is a sort of brute force solution:
select edate,
str_to_date(concat(year(edate), '-', 1 + floor((month(edate) - 1)/ 3)) * 3, '-',
(case when month(edate) in (1, 2, 3, 10, 11, 12) then 31 else 30 end)),
'%Y-%m-%d'
)
from table t
order by edate desc
limit 1;
Here is a SQL Fiddle that demonstrates it.
You can use LAST_DAY to select the last day of a specific month depending on where your quarters end you may have to change the 3,6,9,12 to different months.
select t1.max_date,
(
case
when month(max_date) <= 3
then last_day(concat(year(max_date),'-3-1'))
when month(max_date) <= 6
then last_day(concat(year(max_date),'-6-1'))
when month(max_date) <= 9
then last_day(concat(year(max_date),'-9-1'))
else last_day(concat(year(max_date),'-12-1'))
end
) last_quarter_day
from (
select max(EDATE) max_date from myTable
) t1
I found the simplest answer:
SELECT MAKEDATE(YEAR(edate),1)
+ INTERVAL QUARTER(edate) QUARTER
- INTERVAL 1 DAY
This query takes the first day of year, adds quarters to it and subtracts 1 day to get the last day in wanted quarter. So the required query should look like:
SELECT MAX(edate),
MAKEDATE(YEAR(MAX(edate)),1)
+ INTERVAL QUARTER(MAX(edate)) QUARTER
- INTERVAL 1 DAY
FROM table

adding date_add but keeping in mide weekends

i have a mysql query
SELECT CONCAT('document',LEFT(cases.id,26)) AS 'id',
cases.date_modified,
cases.date_modified,
'67421f0a-3f44-1093-1ab6-51750b508349' AS 'assigned_user','1','1','0',
'complete documentation in 4 Days' AS 'name',
'Not Started',
cases.date_modified,
DATE_ADD(cases.date_modified,INTERVAL 4 DAY) AS 'due date','Cases',cases.id,
'P1','Complete Operations Documentation' AS 'description'
FROM cases
INNER JOIN cases_cstm
ON ( cases.id = cases_cstm.id_c)
WHERE cases.`assigned_user_id` = '67421f0a-3f44-1093-1ab6-51750b508349'
AND cases.`status` = 'Start Administration'
AND `cases_cstm`.`file_location` = 'Operations'
ORDER BY `date_modified` DESC
LIMIT 1;
but the problem is on tuesday it will come up for saterday and wednesday it will come up for sunday
and thursday or friday the people will have 2 days les to work?
how can i check that if a weekend fals in the due date to add 2 days?
regards
Try this expression:
(case when weekday(cases.date_modified) = 0
then DATE_ADD(cases.date_modified, INTERVAL 4 DAY)
else DATE_ADD(cases.date_modified, INTERVAL 6 DAY)
end) as 'due date'
It just tests for the day of the week and then adds the appropriate duration to pass the weekend.
The DAYOFWEEK function will return 1 for Sunday, 2 for Monday, 3 for Tuesday, ... through 7 for Saturday. You can use it in a condition like so:
DATE_ADD(cases.date_modified,
CASE DAYOFWEEK(cases.date_modified)
WHEN 3 THEN INTERVAL 6 DAY
WHEN 4 THEN INTERVAL 5 DAY
ELSE INTERVAL 4 DAY
END AS 'due date'
The example above adds 6 days for a Tuesday (going to the next Monday), 5 days for a Wednesday (going to the next Monday), and 4 for all others. This is different than what you asked for (where Wednesday goes to the next Tuesday rather than Monday), but it may be more appropriate. You can tweak as necessary.