Running total per id within sliding time window in MySql - mysql

I need a query that can tell me number of idObj for the given idTest for Yesterday, 2 day before and 3 day before.
Number of idObj flagged 2 day before should include idObj flagged Yesterday i.e. It only should display number of idObj flagged yesterday as well as 2 day before.
Number of idOjb flagged 3 day before should include idObj flagged Yesterday, 2 day before and 3 day before.
I also need the name of the column as date instead of 'DayBeforeYest' and 'TwoDayBefore'.
Below is what I am looking for:
idTest 2013-06-29 2013-06-28 2013-06-27
104 9 7 5
105 7 6 2
106 5 3 0
Here, on 2013-06-29, idObj counts includes those idObj that has been flagged on only 2013-06-29. On 2013-06-28, idObj count includes those idObj that has been flagged on 2013-06-29 and on 2013-06-28. On 2013-06-27, idObj count includes those idObj that has been flagged on
2013-06-29, 2013-06-28 and 2013-06-27. Therefore, 3 days ago column will have less idObj counts compared to yesterday.
Query
create table tblTest (dateFact date, idTest int, idObj int);
insert into tblTest values
('2013-06-29', 104, 4433), ('2013-06-29', 105, 3345), ('2013-06-29', 106, 5543),
('2013-06-28', 104, 4433), ('2013-06-28', 105, 3345), ('2013-06-28', 106, 4356),
('2013-06-27', 104, 3439), ('2013-06-07', 105, 3345), ('2013-06-07', 106, 8955);
Below is the query I came up with but it just counts number of idObj flagged on 2nd and 3rd day per idTest. It does not take into account of idObj flagged in prevous days. It also doesn't display column name in the date format.
select idTest, max(Yest) as Yest, max(DayBeforeYest) as DayBeforeYest, max(TwoDayBefore) as TwoDayBefore from
(
(select idTest, count(idObj) as Yest, 0 as DayBeforeYest, 0 as TwoDayBefore from tblTest
where dateFact =date_sub(curdate(), interval 1 day) group by idTest)
union
(select idTest, 0 as Yest, count(idObj) DayBeforeYest, 0 as TwoDayBefore from tblTest
where dateFact = date_Sub(curdate(), interval 2 day) group by idTest)
union
(select idTest, 0 as Yest, 0 as DayBeforeYest , count(idObj) TwoDayBefore from tblTest
where dateFact = date_sub(curdate(), interval 3 day) group by idTest) )x
group by idTest;
Thank you!
====================================
Edited:
create table tblTest (dateFact date, idTest int, idObj int);
INSERT INTO tblTest
select CURDATE() - INTERVAL 1 DAY, 104, 4433 UNION ALL
SELECT CURDATE() - INTERVAL 1 DAY, 105, 3345 UNION ALL
SELECT CURDATE() - INTERVAL 1 DAY, 106, 5543 UNION ALL
SELECT CURDATE() - INTERVAL 2 DAY, 104, 4433 UNION ALL
SELECT CURDATE() - INTERVAL 2 DAY, 105, 3345 UNION ALL
SELECT CURDATE() - INTERVAL 2 DAY, 106, 4356 UNION ALL
SELECT CURDATE() - INTERVAL 3 DAY, 104, 3439 UNION ALL
SELECT CURDATE() - INTERVAL 3 DAY, 105, 3345 UNION ALL
SELECT CURDATE() - INTERVAL 3 DAY, 106, 8955;
For the given example, output should be as below:
idTest 2013-06-30 2013-06-29 2013-06-28
104 1 1 0
105 1 1 1
106 1 0 0
On 2013-06-30 for idTest 104, we have 1 idObj 4433. On 2013-06-29 for idTest 104 we have 1 idObj 4433 which is also in 2013-06-30 for idTest 104.
On 2013-06-28 for idTest 104 we have 1 idObj 3439 which is not in either 2013-06-30 or 2013-06-29 for idTest 104. Therefore, you will see row values for 104 to be 1 1 0.
On 2013-06-30 for idTest 105, we have 1 idObj 3345. On 2013-06-29 for idTest 105 we have 1 idObj 3345 which is also in 2013-06-30 idTest 105.
On 2013-06-28 for idTest 105, we have 1 idObj 3345 which is also in 2013-06-30 and 2013-06-29. Therefore, you will see row values to be 1 1 1.
And so on...
On 2013-06-28, to count the idObj, it should be present in 2013-06-28, 213-06-29, 2013-06-30.
On 2013-06-29, to count the idObj, it should be present in 2013-06-29 and 2013-06-30.
On 2013-06-30, to count the idObj, it should be present in 2013-06-30.

UPDATED To make column names to be dates you have to use dynamic SQL.
SET #sql = CONCAT(
'SELECT idTest
, SUM(d1) `', DATE_FORMAT(CURDATE() - INTERVAL 1 DAY, '%Y-%m-%d'),
'`, SUM(d2 = 1 AND d1 = 1) `', DATE_FORMAT(CURDATE() - INTERVAL 2 DAY, '%Y-%m-%d'),
'`, SUM(d3 = 1 AND d2 = 1 AND d1 = 1) `', DATE_FORMAT(CURDATE() - INTERVAL 3 DAY, '%Y-%m-%d'),
'` FROM
(
SELECT idTest
,idObj
,SUM(CASE WHEN dateFact = CURDATE() - INTERVAL 1 DAY THEN 1 ELSE 0 END) d1
,SUM(CASE WHEN dateFact = CURDATE() - INTERVAL 2 DAY THEN 1 ELSE 0 END) d2
,SUM(CASE WHEN dateFact = CURDATE() - INTERVAL 3 DAY THEN 1 ELSE 0 END) d3
FROM tblTest
WHERE dateFact BETWEEN CURDATE() - INTERVAL 3 DAY AND CURDATE() - INTERVAL 1 DAY
GROUP BY idTest, idObj
) q
GROUP BY idTest');
PREPARE stmt FROM #sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Sample output:
| IDTEST | 2013-07-02 | 2013-07-01 | 2013-06-30 |
-------------------------------------------------
| 104 | 1 | 1 | 0 |
| 105 | 1 | 1 | 1 |
| 106 | 1 | 0 | 0 |
Here is SQLFiddle demo
To make life easier on client (calling) side you can wrap this code into a stored procedure
DELIMITER $$
CREATE PROCEDURE sp_test_report()
BEGIN
-- put above mentioned code here
END$$
DELIMITER ;
And then use it
CALL sp_test_report();
Here is SQLFiddle demo

Related

calculate 2 days prior and 2 days after sales

wants to calculate 2 days prior and 2 days after sales
total_2_days_prior_sales = before 2 days to current date sales sum
total_2_days_prior_sales = from current date to next 2 days sales sum
Requirement:
Live Code:
http://sqlfiddle.com/#!9/d88bee/15
My Try:
CREATE TABLE test (
end_date date,
sales int
);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-01',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-01',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-02',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-02',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-03',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-04',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-05',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-06',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-07',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-08',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-08',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-09',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-10',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-11',10);
INSERT INTO test (end_Date, sales)
VALUES ('2022-01-12',10);
Code:
select
end_Date,
-- DATE_SUB(date(end_Date), INTERVAL 2 day),
-- DATE_SUB(date(end_Date), INTERVAL -2 day),
-- DATE_SUB(date(end_Date), INTERVAL 0 day),
SUM(sales) as CurrentSales,
SUM(case when end_Date between DATE_SUB(date(end_Date), INTERVAL 2 day) and DATE_SUB(date(end_Date), INTERVAL 0 day) then sales else 0 end) total_2_days_prior_sales,
SUM(case when end_Date between DATE_SUB(date(end_Date), INTERVAL 0 day) and DATE_SUB(date(end_Date), INTERVAL -2 day) then sales else 0 end) total_2_days_after_sales
from test
group by end_Date
Since MySQL 5.6 does not support window functions and CTE, you can use subqueries to get the totals for prior sales and after sales, like this
SELECT
*,
(SELECT SUM(t.sales)
FROM test t
WHERE t.end_date BETWEEN DATE_SUB(s.end_Date, INTERVAL 1 day) AND s.end_date
GROUP BY s.end_date) total_2_days_prior_sales,
(SELECT SUM(t.sales)
FROM test t
WHERE t.end_date BETWEEN s.end_date AND DATE_ADD(s.end_Date, INTERVAL 1 day)
GROUP BY s.end_date) total_2_days_after_sales
FROM (
SELECT
end_Date,
SUM(sales) CurrentSales
FROM test
GROUP BY end_Date
) s
Output
end_Date
CurrentSales
total_2_days_prior_sales
total_2_days_after_sales
2022-01-01
20
20
40
2022-01-02
20
40
30
2022-01-03
10
30
20
2022-01-04
10
20
20
2022-01-05
10
20
20
2022-01-06
10
20
20
2022-01-07
10
20
30
2022-01-08
20
30
30
2022-01-09
10
30
20
2022-01-10
10
20
20
2022-01-11
10
20
20
2022-01-12
10
20
10
If to change the interval from 2 days to 3 days, output is like this
end_Date
CurrentSales
total_3_days_prior_sales
total_3_days_after_sales
2022-01-01
20
20
50
2022-01-02
20
40
40
2022-01-03
10
50
30
2022-01-04
10
40
30
2022-01-05
10
30
30
2022-01-06
10
30
40
2022-01-07
10
30
40
2022-01-08
20
40
40
2022-01-09
10
40
30
2022-01-10
10
40
30
2022-01-11
10
30
20
2022-01-12
10
30
10
You can check a sqlfiddle here
Also you can use a self JOIN with your table and calculate sub totals conditionally like this
SELECT
s.end_date,
s.sales,
SUM(CASE WHEN t.end_date <= s.end_date
THEN t.sales
END) prev_sales,
SUM(CASE WHEN t.end_date >= s.end_date
THEN t.sales
END) after_sales
FROM (
SELECT
end_date,
SUM(sales) sales
FROM test
GROUP BY end_date
) s
JOIN test t ON t.end_date BETWEEN DATE_SUB(s.end_Date, INTERVAL 1 day) AND DATE_ADD(s.end_Date, INTERVAL 1 day)
GROUP BY end_date
This query produces the same output.
You can check it here
In general, a join should perform better.
Also you need a composite index on the end_date and sales columns in your table.

MYSQL Select priority data if exist

My current data :
Month Price A Price B Status Approval
January 1000 2000 1 0
February 1000 2000 1 0
March 1000 2000 1 0
April 1000 2000 1 0
May 1000 2000 1 0
June 1000 2000 1 0
July 1000 2000 1 0
August 1000 2000 1 0
September 1000 2000 1 0
October 1000 3000 1 0
October 2000 2000 2 0
October 3000 2000 2 1
November 1000 2000 1 0
December 1000 2000 1 0
*Status 1 = Not Changed, Status 2 = Changed, Approval 1 = Approved
What i'm trying to show,is when month > 1 (my case is October)
,IF STATUS = 2 AND APPROVAL = 1 IS NOT EXIST,Show data with
STATUS = 1 AND APPROVAL = 0ELSE SHOW STATUS = 2 AND APPROVAL =
1 Using group by, doesn't work,it shows first data if month more
than 1
My Query :
SELECT A.NAME AS MONTH,
IFNULL( B.PRICE_A, 0 ) PRICE_A,
IFNULL( B.PRICE_B, 0 ) PRICE_B,
STATUS,
APPROVAL,
FROM
REF_MONTH A
LEFT OUTER JOIN (
SELECT
SUBSTR( PERIOD, '5,2' ) MONTH,
ROUND( PRICE_A_FIX, 2 ) PRICE_A,
ROUND( PRICE_B_FIX, 2 ) PRICE_B,
A.STATUS,
A.APPROVAL,
FROM
PRICE_MONTH_LIST A
WHERE
SUBSTR( PERIOD, 1, 4 ) = 2018
) B ON B.MONRH= A.MONTH
WHERE DATE_FORMAT( STR_TO_DATE( CONCAT( 2018, month), '%Y%m' ), '%Y%m' ) <=
DATE_FORMAT( SYSDATE( ), '%Y%m' )
GROUP BY A.MONTH
ORDER BY A.ID;
My Expected Result :
Month Price A Price B Status Approval
January 1000 2000 1 0
February 1000 2000 1 0
March 1000 2000 1 0
April 1000 2000 1 0
May 1000 2000 1 0
June 1000 2000 1 0
July 1000 2000 1 0
August 1000 2000 1 0
September 1000 2000 1 0
October 3000 2000 2 1
November 1000 2000 1 0
December 1000 2000 1 0
Below would be the query -
with table1 as
(
select 'January' as month, 1000 as priceA, 2000 as priceB, 1 as status, 0 as approval from dual
union all
select 'October' as month, 1000 as priceA, 3000 as priceB, 1 as status, 0 as approval from dual
union all
select 'October' as month, 2000 as priceA, 2000 as priceB, 2 as status, 0 as approval from dual
union all
select 'October' as month, 3000 as priceA, 2000 as priceB, 2 as status, 1 as approval from dual
)
,t1 as
(
select month, count(*) as cnt, min(status) as min_status,
max(status) max_status, min(approval) min_app, max(approval) max_app from table1
group by month
)
,t2 as
(
select
month,
case when cnt>1 and max_status<>2 and max_app<>1 then min_status else max_status end as status1,
case when cnt>1 and max_status<>2 and max_app<>1 then min_app else max_app end as approval1
from t1
)
select
t.month,
t.priceA,
t.priceB,
t.status,
t.approval
from table1 t
inner join t2 on t.month=t2.month and t.status=t2.status1 and t.approval=t2.approval1;
result -
January 1000 2000 1 0
October 3000 2000 2 1
As there were no insert scripts, I have use CTE with oralce db.
Hope this helps.

MySQL - How to populate weekly data in a month

How to select data from following table group by weeks in a month
Date Project Value Week
+----------+--------------+-------+------+
2018-11-07 A 2 45
2018-11-08 B 4 45
2018-11-09 C 3 45
2018-11-12 B 6 46
2018-11-13 A 5 46
2018-11-14 C 6 46
(First week is end on sunday or week number in a month)
So my result should look like this.
Project 1st Week 2nd Week 3rd Week 4th Week 5th Week
+----------+--------+--------+--------+--------+--------
A 0 2 5 0 0
B 0 4 6 0 0
C 0 3 6 0 0
I try this one :
SELECT project, value, week, date
FROM module_progress
WHERE
created_at BETWEEN '2018-11-01 00:00:00' AND '2018-11-31
AND date > DATE_SUB(NOW(), INTERVAL 1 WEEK) 23:59:59'
GROUP BY week
Thank you
Just use a sub query to get first week no for the month, and sum case statements for each week:
select year(date) as y, month(date) as m, project,
sum(case when week=w0 then value else 0 end) as w1,
sum(case when week=w0+1 then value else 0 end) as w2,
sum(case when week=w0+2 then value else 0 end) as w3,
sum(case when week=w0+3 then value else 0 end) as w4,
sum(case when week=w0+4 then value else 0 end) as w5
from #date d
join (select year(date) as y, month(date) as m, min(week) as w0 from #date group by year(date), month(date))
as d0 on d0.y=year(date) and d0.m=month(date)
group by year(date), month(date), project

MYSQL - Update row when the date more than 1 year

I am had a query could able to update the row if DateTimeAdded is 1 year or more. But i find out that it wouldn't work in leap year. Anyone have better suggestion?
CREATE EVENT UpdateProduct
ON SCHEDULE
EVERY 1 DAY
DO
update `product` set Label = "ClearStock" where datediff(now(),
DateTimeAdded) >= 365
To identify rows that have DateTimeAdded value over a year old, you could do something like this:
... WHERE DateTimeAdded < NOW() + INTERVAL -1 YEAR
FOLLOWUP
Demonstration:
SELECT NOW() + INTERVAL 0 HOUR AS `now`
, DATE(NOW()) + INTERVAL -1 YEAR AS `year_ago`
, t.DateTimeAdded
, t.DateTimeAdded < DATE(NOW()) + INTERVAL -1 YEAR AS `compare`
FROM ( SELECT '2015-01-24 11:00:00' AS `DateTimeAdded`
UNION ALL
SELECT '2015-01-25 13:00:00'
UNION ALL
SELECT '2015-01-26 14:00:00'
) t
returns:
NOW year_ago DateTimeAdded compare
------------------- ---------- ------------------- -------
2016-01-25 22:11:56 2015-01-25 2015-01-24 11:00:00 1
2016-01-25 22:11:56 2015-01-25 2015-01-25 13:00:00 0
2016-01-25 22:11:56 2015-01-26 2015-01-26 14:00:00 0

Employee Whole Attendance Query

I am stucked with this problem from long time. Though you will find this is big question, but it's not............
I have following tables, with dummy data, so you can also try it.
users Table with Columns
emp_id emp_Name Joining_Date state_id
1 Lauren 11-07-2011 123
2 John 01-08-2012 234
3 Smith 02-09-2011 234
____________________________________________________
CREATE TABLE users
( emp_id int
, emp_Name varchar(20)
, Joining_Date DATE
, state_id int
);
INSERT INTO users (emp_id, emp_Name, Joining_Date, state_id)
VALUES
(1, 'John', '2011-08-10', 123) ,
(2, 'Smith', '2011-09-11', 234) ;
__________________________________________________________________
cl_doctor_call Table
Subject Call_Date call_Done_By(emp_id)
Call 15-01-2012 1
CA 21-02-2012 2
___________________________________________________________________
CREATE TABLE cl_doctor_call
( Subject VARCHAR(10)
, Call_Date DATE
, call_Done_By INT
) ;
INSERT INTO cl_doctor_call (Subject, Call_Date,call_Done_By)
VALUES
('sub1', '2011-08-15', 1) ,
('sub2', '2011-09-16', 2) ;
___________________________________________________________________
cl_ chemist Table
Subject Call_Date call_Done_By(emp_id)
Chemist 1-02-2012 2
Texo 21-03-2012 1
____________________________________________________________________________________
CREATE TABLE cl_chemist ( Subject VARCHAR(10), Call_Date DATE, call_Done_By INT );
INSERT INTO cl_chemist (Subject, Call_Date,call_Done_By) VALUES ('sub3','2011-08-19',2),('sub5','2011-09-25',1);
___________________________________________________________
cl_Stock Table
Subject Call_Date call_Done_By(emp_id)
Sub1 1-02-2012 1
Sub2 21-03-2012 3
____________________________________________________________
CREATE TABLE cl_Stock
( Subject VARCHAR(10)
, Call_Date DATE
, call_Done_By INT
);
INSERT INTO cl_Stock (Subject, Call_Date,call_Done_By)
VALUES
('ABC', '2011-10-13', 1) ,
('sub5', '2011-11-17', 2) ;
______________________________________________________
Meetings Table
Subject Meeting_Date call_Done_By(emp_id)
Sub1 11-02-2012 1
Sub2 23-03-2012 2 _____________________________________________________________________________________
CREATE TABLE Meetings ( Subject VARCHAR(10), meet_Date DATE, meet_Done_By INT );
INSERT INTO Meetings (Subject, meet_Date,meet_Done_By)
VALUES
('Planning','2011-11-01',2),
('Deploy','2011-12-15',1);
______________________________________________________________________________________
Leave Table
Subject from_Date to_date Requested_By(emp_id) status
Sub1 01-02-2012 03-02-2012 2 Declined
Sub2 21-03-2012 22-03-2012 1 Approved
Holiday Table
Holiday_Name Holiday_Date States_Id
New Year 01-01-2012 123
Independence Day 15-08-2012 234
______________________________________________________________________________________
CREATE TABLE Holiday ( Holiday_Name VARCHAR(10),Holiday_Date DATE, State_Id_c INT );
INSERT INTO Holiday (Holiday_Name,Holiday_Date,State_Id_c) VALUES ('NEW_YEAR','2012-01-01',123), ('CHRISHMAS','2011-12-25',234);
______________________________________________________________________________________
Replace with date
for stock='Y'
for chemist='Y'
for doctor='Y'
for leave='L'
for Sunday='S'
for meeting ='M'
for Holiday='H'
Hope so still you are with me.
Now Admin will select 'month' and 'year' and according to that attendance report for
employee will displayed.
Output :
Employee Year Month 1 2 3 4 5 6 7.... for all 31 days
John 2011 Nov Y Y Y H Y L S....
Smith 2011 Nov Y Y Y H Y M S.....
. . . ................
. . . ................
&so on &so on &so on & so on
here in output 1,2,3.... are days from 0-31 for a month which we can write using 'case'
Consider if employee is present on day show its status as 'Y' ,if he is on leave show it's status as 'L; if there is Sunday show status 'S' for holiday show 'H' and so on.
So basically I want a write a query to retrieve all these details.
So pl z suggest me ways here, that How can I display this attendance Report by a query or procedure.
I have tried so far this .....
DELIMITER $$
USE `leosatyen_claris`$$
DROP PROCEDURE IF EXISTS `Test`$$
CREATE DEFINER=`leosatyen_claris`#`%` PROCEDURE `Test`(IN month_last_date DATE)
BEGIN
SELECT
users.id AS Id,
users.first_name AS Employee,
CASE MAX(CASE WHEN DATE_FORMAT(main.cdate,'%d')='01' THEN main.task
WHEN DATE_FORMAT(DATE_ADD(month_last_date, INTERVAL 1 DAY),'%W')='SUNDAY' THEN 0
WHEN main.cdate IS NULL THEN -1
ELSE -2 END)
WHEN -1 THEN 'NA'
WHEN 0 THEN 'S'
WHEN 1 THEN 'Y'
WHEN 2 THEN 'C'
WHEN 3 THEN 'S1'
WHEN 4 THEN 'P'
WHEN 5 THEN 'M'
END Day1,
CASE MAX(CASE WHEN DATE_FORMAT(main.cdate,'%d')='02' THEN main.task
WHEN DATE_FORMAT(DATE_ADD(month_last_date, INTERVAL 2 DAY),'%W') ='SUNDAY' THEN 0
WHEN main.cdate IS NULL THEN -1
ELSE -2 END)
WHEN -1 THEN 'NA'
WHEN 0 THEN 'S'
WHEN 1 THEN 'Y'
WHEN 2 THEN 'C'
WHEN 3 THEN 'S1'
WHEN 4 THEN 'P'
WHEN 5 THEN 'M'
END Day2,
.
.
. ## UP TO 31 DAYS
CASE MAX(CASE WHEN DATE_FORMAT(main.cdate,'%d')='31' THEN main.task
WHEN DATE_FORMAT(DATE_ADD(month_last_date, INTERVAL 31 DAY),'%W')='SUNDAY' THEN 0
WHEN main.cdate IS NULL THEN -1
ELSE -2 END)
WHEN -1 THEN 'NA'
WHEN 0 THEN 'S'
WHEN 1 THEN 'Y'
WHEN 2 THEN 'C'
WHEN 3 THEN 'S1'
WHEN 4 THEN 'P'
WHEN 5 THEN 'M'
END Day31
FROM
users
LEFT JOIN
(
SELECT DATE_FORMAT(cl_doctor_call.date_entered,'%Y-%m-%d')AS cdate,
cl_doctor_call.created_by AS emp,
1 task
FROM
cl_doctor_call
WHERE
DATE_FORMAT(cl_doctor_call.date_entered,'%Y-%m-%d')>month_last_date AND
DATE_FORMAT(cl_doctor_call.date_entered,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT
DATE_FORMAT(cl_chemist_call.date_entered,'%Y-%m-%d') AS cdate,
cl_chemist_call.created_by AS emp,
2 task
FROM
cl_chemist_call
WHERE
DATE_FORMAT(cl_chemist_call.date_entered,'%Y-%m-%d')>month_last_date AND
DATE_FORMAT(cl_chemist_call.date_entered,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT
DATE_FORMAT(cl_stockist_call_cstm.calldate_c,'%Y-%m-%d') AS cdate,
cl_stockist_call.created_by AS emp,
3 task
FROM
cl_stockist_call LEFT JOIN cl_stockist_call_cstm
ON cl_stockist_call.id=cl_stockist_call_cstm.id_c
WHERE
DATE_FORMAT(cl_stockist_call_cstm.calldate_c,'%Y-%m-%d')> month_last_date AND
DATE_FORMAT(cl_stockist_call_cstm.calldate_c,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT DATE_FORMAT(cl_product_pramotional_call.date_entered,'%Y-%m-%d') AS cdate,
cl_product_pramotional_call.created_by AS emp,
4 task
FROM cl_product_pramotional_call
WHERE
DATE_FORMAT(cl_product_pramotional_call.date_entered,'%Y-%m-%d')>month_last_date AND
DATE_FORMAT(cl_product_pramotional_call.date_entered,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT DATE_FORMAT(meetings.date_start,'%Y-%m-%d') AS cdate,
meetings.created_by AS emp,
5 task
FROM meetings
WHERE
DATE_FORMAT(meetings.date_start,'%Y-%m-%d')> month_last_date AND
DATE_FORMAT(meetings.date_start,'%Y-%m-%d') <= DATE_ADD(month_last_date, INTERVAL 30 DAY)
)AS main
ON main.emp = users.id
WHERE DATE_FORMAT(users.date_entered,'%Y-%m-%d')<= month_last_date
GROUP BY users.id ;
END$$
DELIMITER ;
Here I am getting all Sunday's of that month AND All customer calls like Doctor_call,
chemist call, stockist call and meetings entries correctly.
Now I just need to add 'Leave' and Holiday Entries. So anybody can assist me to achieve holidays and leave in my existing procedure?
any suggestions will be helpful for me....
Finally I achieved answer for Attendance Report.
We need to execute this lengthy stored procedure to get monthly attendance of all Employees.
To execute this procedure we need to pass IN parameter as last date of previous month like if we need to see December 2011 attendance Report pass '2011-11-30' AS IN parameter.
DELIMITER $$
USE `Sample`$$
DROP PROCEDURE IF EXISTS `Test`$$
CREATE DEFINER=`Sample`#`%` PROCEDURE `Test`(IN month_last_date DATE)
BEGIN
SELECT
users.id AS Id,DATE_FORMAT(month_last_date,'%Y')AS YEAR,DATE_FORMAT(month_last_date,'%M')AS MONTH,
CONCAT(users.first_name,users.last_name) AS Employee,cl_territories.name AS Territory,
CASE MAX(CASE WHEN DATE_FORMAT(main.cdate,'%d')='01' THEN main.task
WHEN DATE_FORMAT(DATE_ADD(month_last_date, INTERVAL 1 DAY),'%W')='SUNDAY' THEN 0
WHEN main.cdate IS NULL THEN -1
ELSE -2 END)
WHEN -1 THEN 'NA'
WHEN 0 THEN 'S'
WHEN 1 THEN 'Y'
WHEN 2 THEN 'C'
WHEN 3 THEN 'S1'
WHEN 4 THEN 'P'
WHEN 5 THEN 'M'
WHEN 6 THEN 'H'
WHEN 7 THEN 'L'
END Day1,
CASE MAX(CASE WHEN DATE_FORMAT(main.cdate,'%d')='02' THEN main.task
WHEN DATE_FORMAT(DATE_ADD(month_last_date, INTERVAL 2 DAY),'%W') ='SUNDAY' THEN 0
WHEN main.cdate IS NULL THEN -1
ELSE -2 END)
WHEN -1 THEN 'NA'
WHEN 0 THEN 'S'
WHEN 1 THEN 'Y'
WHEN 2 THEN 'C'
WHEN 3 THEN 'S1'
WHEN 4 THEN 'P'
WHEN 5 THEN 'M'
WHEN 6 THEN 'H'
WHEN 7 THEN 'L'
END Day2,
.
.
. # upto 31 days
CASE MAX(CASE WHEN DATE_FORMAT(main.cdate,'%d')='31' THEN main.task
WHEN DATE_FORMAT(DATE_ADD(month_last_date, INTERVAL 31 DAY),'%W')='SUNDAY' THEN 0
WHEN main.cdate IS NULL THEN -1
ELSE -2 END)
WHEN -1 THEN 'NA'
WHEN 0 THEN 'S'
WHEN 1 THEN 'Y'
WHEN 2 THEN 'C'
WHEN 3 THEN 'S1'
WHEN 4 THEN 'P'
WHEN 5 THEN 'M'
WHEN 6 THEN 'H'
WHEN 7 THEN 'L'
END Day31
FROM
users LEFT JOIN users_cstm
ON users.id=users_cstm.id_c
LEFT JOIN cl_territories
ON users_cstm.cl_territories_id1_c=cl_territories.id
LEFT JOIN
(
SELECT DATE_FORMAT(cl_doctor_call.date_entered,'%Y-%m-%d')AS cdate,
cl_doctor_call.created_by AS emp,
1 task
FROM
cl_doctor_call
WHERE
DATE_FORMAT(cl_doctor_call.date_entered,'%Y-%m-%d')>month_last_date AND
DATE_FORMAT(cl_doctor_call.date_entered,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT
DATE_FORMAT(cl_chemist_call.date_entered,'%Y-%m-%d') AS cdate,
cl_chemist_call.created_by AS emp,
2 task
FROM
cl_chemist_call
WHERE
DATE_FORMAT(cl_chemist_call.date_entered,'%Y-%m-%d')>month_last_date AND
DATE_FORMAT(cl_chemist_call.date_entered,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT
DATE_FORMAT(cl_stockist_call_cstm.calldate_c,'%Y-%m-%d') AS cdate,
cl_stockist_call.created_by AS emp,
3 task
FROM
cl_stockist_call LEFT JOIN cl_stockist_call_cstm
ON cl_stockist_call.id=cl_stockist_call_cstm.id_c
WHERE
DATE_FORMAT(cl_stockist_call_cstm.calldate_c,'%Y-%m-%d')> month_last_date AND
DATE_FORMAT(cl_stockist_call_cstm.calldate_c,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT DATE_FORMAT(cl_product_pramotional_call.date_entered,'%Y-%m-%d') AS cdate,
cl_product_pramotional_call.created_by AS emp,
4 task
FROM cl_product_pramotional_call
WHERE
DATE_FORMAT(cl_product_pramotional_call.date_entered,'%Y-%m-%d')>month_last_date AND
DATE_FORMAT(cl_product_pramotional_call.date_entered,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT DATE_FORMAT(meetings.date_start,'%Y-%m-%d') AS cdate,
meetings.created_by AS emp,
5 task
FROM meetings
WHERE
DATE_FORMAT(meetings.date_start,'%Y-%m-%d')> month_last_date AND
DATE_FORMAT(meetings.date_start,'%Y-%m-%d') <= DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT DATE_FORMAT(cl_holidays_structures.holiday_date,'%Y-%m-%d') AS cdate,
users.id AS emp,
6 task
FROM users LEFT JOIN users_cstm
ON users.id=users_cstm.id_c
LEFT JOIN cl_states
ON users_cstm.cl_states_id1_c=cl_states.id
LEFT JOIN cl_holidays_structures
ON cl_holidays_structures.cl_states_id_c=users_cstm.cl_states_id1_c
WHERE
DATE_FORMAT(cl_holidays_structures.holiday_date,'%Y-%m-%d')> month_last_date AND
DATE_FORMAT(cl_holidays_structures.holiday_date,'%Y-%m-%d') <= DATE_ADD(month_last_date, INTERVAL 30 DAY)
UNION ALL
SELECT cl_leave_management_cstm.from_date_c+ INTERVAL td.days DAY cdate,
users.id AS emp,
7 task
FROM
cl_leave_management LEFT JOIN cl_leave_management_cstm
ON cl_leave_management.id=cl_leave_management_cstm.id_c
LEFT JOIN users
ON cl_leave_management.created_by = users.id
JOIN temp_days td
ON DATEDIFF(cl_leave_management_cstm.to_date_c, cl_leave_management_cstm.from_date_c) >= td.days
WHERE DATE_FORMAT(cl_leave_management_cstm.from_date_c,'%Y-%m-%d')> month_last_date AND
DATE_FORMAT(cl_leave_management_cstm.from_date_c,'%Y-%m-%d')<=DATE_ADD(month_last_date, INTERVAL 30 DAY) AND
cl_leave_management_cstm.status_c='Approved'
)AS main
ON main.emp = users.id
WHERE DATE_FORMAT(users.date_entered,'%Y-%m-%d')<= month_last_date
GROUP BY users.id ;
END$$
DELIMITER ;
Thanks to all who guide me to get this result.