Getting the missing period through mmysql query or procedure..? - mysql

I have a table customer_order as follows
mysql> select * from customer_order;
+---------+---------+-----------+------------------+----------------+
| cust_id | orderno | region_cd | order_start_date |order_del_date |
+---------+---------+-----------+------------------+----------------+
| CU_082 | ONO_001 | reg1 | 2012-04-25 | 2012-08-25 |
| CU_082 | ONO_002 | reg1 | 2012-04-28 | 2012-11-28 |
| CU_083 | ONO_002 | reg2 | 2012-04-28 | 2012-11-28 |
| CU_082 | ONO_003 | reg1 | 2012-04-25 | 2012-08-25 |
| CU_084 | ONO_004 | reg4 | 2012-04-25 | 2012-10-25 |
I need a table like this...which i get....as follows
mysql> select order_start_date,order_del_date,orderno,cust_id from customer_order wh
ere order_start_date >= '2012-04-25' AND order_del_date <='2012-12-28' and cust_i
d IN ('36082','36088') order by cust_id ;
+------------------+----------------+---------+---------+
| order_start_date | order_del_date | pid | emp_id |
+------------------+----------------+---------+---------+
| 2012-04-25 | 2012-05-25 | ONO_001 | CU_082 |
| 2012-08-22 | 2012-12-28 | ONO_004 | CU_082 |
| 2012-06-22 | 2012-08-28 | ONO_003 | CU_082 |
| 2012-05-27 | 2012-06-25 | ONO_002 | CU_082 |
| 2012-04-25 | 2012-05-25 | ONO_001 | CU_082 |
| 2012-05-27 | 2012-06-25 | ONO_001 | CU_082 |
| 2012-04-30 | 2012-06-25 | ONO_001 | CU_088 |
| 2012-06-28 | 2012-07-15 | ONO_002 | CU_088 |
| 2012-07-28 | 2012-08-25 | ONO_003 | CU_088 |
| 2012-07-16 | 2012-09-25 | ONO_004 | CU_088 |
+------------------+----------------+---------+---------+
now i need to query on this table ...
to get
for each customer here we get data for the period from wat date to wat date his order processing details in the above table..
now for each customer i shld find the period for which thr is no order processing...
eg cust_id =CU_088
he has his order processed from 30 apr to 25 june
den from 28th june to 15 july
(here thr is a diff that is thr is no order taken or any processing done from 26th to 27th june..this is wat is the required result)
**one more imp consideration is...
in the next entry we find thr is a order process from 28th july to 25th aug
w.r.t previous entry i.e, 28th june to 15july we find that for this customer thr is no order taken or processed from 16th to 27th july..
but with the last entry tat is 16th july to 25th sept he has an order with different order_no thrfore the gap 16th july to 27th july is filled here so this kind of a condition also needs to be checked...
I need to get the output as something like this..
+------------------+----------------+---------+---------+
| order_start_date | order_del_date | pid | emp_id |
+------------------+----------------+---------+---------+
| 2012-06-26 | 2012-06-27 | ONO_001 | CU_088 |
+------------------+----------------+---------+---------+
that is either the query or procedure which is more efficient should give me the period wer in thr was no action done for customer...
help me write the query which does the all the above things.
I m new to db queries..so please help me out..

To fetch every 'gap' between orders, you can use a self-join:
SELECT o1.cust_id,
o1.order_del_date + INTERVAL 1 DAY AS gap_begin,
MIN(o2.order_start_date) - INTERVAL 1 DAY AS gap_end
FROM customer_order o1
JOIN customer_order o2 ON o1.cust_id = o2.cust_id
AND o1.order_del_date <= o2.order_start_date
GROUP BY o1.cust_id, o1.order_del_date
HAVING gap_begin < gap_end

Related

Sum and subtract from another relation table in one query

I have two tables, one is called Attendance and the other is called Timeslices, I am trying to get the total seconds of Attendances subtracted from Timeslices for the current week and also with Doctrine.
I've got to get the rows but I have to sum and subtract each of them out of the query, but I need to learn to do it in one query.
This is the structure of the Attendance Table:
SELECT * FROM attendance;
+----+---------+---------------------+--------+---------------------+---------------------+
| id | user_id | day | status | check_in | check_out |
+----+---------+---------------------+--------+---------------------+---------------------+
| 1 | 1 | 2019-12-18 00:00:00 | end | 2019-12-18 09:52:00 | 2019-12-18 23:37:02 |
| 2 | 1 | 2019-12-19 00:00:00 | end | 2019-12-19 12:12:00 | 2019-12-19 21:05:00 |
+----+---------+---------------------+--------+---------------------+---------------------+
Timeslice table:
SELECT * FROM timeslice;
+----+---------------+-------------------------------------+---------------------+---------------------+---------------------+
| id | attendance_id | title | day | start_at | stopped_at |
+----+---------------+-------------------------------------+---------------------+---------------------+---------------------+
| 20 | 1 | Sacar al perro, ducharme y vestirme | 2019-12-18 00:00:00 | 2019-12-18 15:57:50 | 2019-12-18 12:15:36 |
| 21 | 1 | Dormir | 2019-12-18 00:00:00 | 2019-12-18 18:44:30 | 2019-12-18 16:16:44 |
| 22 | 1 | Descansar | 2019-12-18 00:00:00 | 2019-12-18 23:04:53 | 2019-12-18 20:56:29 |
| 23 | 2 | Comer | 2019-12-19 00:00:00 | 2019-12-19 16:03:00 | 2019-12-19 15:37:00 |
| 24 | 2 | Comer | 2019-12-19 00:00:00 | 2019-12-19 16:55:00 | 2019-12-19 16:17:00 |
| 25 | 2 | ducharme | 2019-12-19 00:00:00 | 2019-12-19 19:58:00 | 2019-12-19 17:20:00 |
+----+---------------+-------------------------------------+---------------------+---------------------+---------------------+
This is my current query in which I get the results, but then I have to calculate out of the query to get the desired result and SQLFiddle:
http://sqlfiddle.com/#!9/646be/3
SELECT SUM(TIME_TO_SEC(TIMEDIFF(a.check_out, a.check_in))) AS secondsAttendance
, ( SELECT SUM(TIME_TO_SEC(TIMEDIFF(t.start_at, t.stopped_at)))
FROM timeslice t
WHERE t.attendance_id = a.id
) secondsPauses
FROM attendance a
GROUP
BY a.id
What I need as I said before is to be able to do it in the same query without having to use PHP and with Doctrine
I've changed my answer after your comments. If you only need the value it seams that all you need to do is to use you initial query (with a few twicks) as a
subquery in the FROM clause (Derived Table) and then, do your calculations over it. In this case simply need to SUM the result of subtracting the secondsPauses to the secondsAttendance, like this:
-- make the calculation you need over the results
SELECT SUM(Results.secondsAttendance - Results.secondsPauses) as ActualValue
FROM (
-- use you initial results as a subquery and name it as Results
SELECT
SUM(TIME_TO_SEC(TIMEDIFF(a.check_out, a.check_in))) AS secondsAttendance,
(SELECT SUM(TIME_TO_SEC(TIMEDIFF(t.start_at, t.stopped_at)))
FROM timeslice t WHERE t.attendance_id = a.id) AS secondsPauses
FROM attendance a
-- filter date for the current week
where yearweek(DATE(a.check_in), 1) = yearweek(curdate(), 1)
GROUP BY a.id
) Results;
The result is:
+-------------+
| ActualValue |
+-------------+
| 38258 |
+-------------+
SqlFiddle in here

Displaying records from database by quarter in mysql

I have a table named nca_totals.
Table: nca_totals
+----------+-----------+------------+--------------+
| total_id | nca_total | nca_date | account_type |
+----------+-----------+------------+--------------+
| 13 | 10450 | 2015-01-21 | DBP-TRUST |
| 14 | 5000 | 2015-02-05 | DBP-TRUST |
| 15 | 7000 | 2015-04-02 | DBP-TRUST |
| 16 | 4000 | 2015-05-02 | DBP-TRUST |
+----------+-----------+------------+--------------+
Now I want to display all the data by quarter base on its date. Let's say I want to display all the records who belong to 1st Quarter like this:
+----------+-----------+------------+--------------+
| total_id | nca_total | nca_date | account_type |
+----------+-----------+------------+--------------+
| 13 | 10450 | 2015-01-21 | DBP-TRUST |
| 14 | 5000 | 2015-02-05 | DBP-TRUST |
+----------+-----------+------------+--------------+
This date belongs to the 1st quarter of the year (Jan, Feb, March). I only have this query to select the date and return its quarter number as:
SELECT QUARTER('2015-01-11'); /* returns 1 */
How can I combine that query to display all the records by quarter ? Can anyone help ? Thanks.
select *
from nca_totals
where QUARTER(nca_date) = 1
SELECT
CEIL(MONTH(`nca_date`) / 3) AS `quarter`
FROM `nca_totals`;

Simple MySql SELECT

I have a table that assigns workdays to worker-IDs.
Table: workdays Table: jobs
+------+-------+ +------+-----------+
| id | days | | id | jobs |
+------+-------+ +------+-----------+
| 1 | mon | | 1 | cleaning |
| 1 | tue | | 2 | cooking |
| 2 | sat | | 3 | driving |
| 3 | mon | | 4 | cleaning |
| 3 | tue | | 5 | cooking |
| 3 | sat | +------+-----------+
| 4 | wed |
| 4 | mon |
| 5 | tue |
+------+-------+
This is the query I use to select the IDs of people who work on any of the days I specify (say Monday and Tuesday):
SELECT * FROM workdays WHERE days IN ( 'mon', 'tue' )
Now I'd like to select those people who work on ALL of the days I specify. How can I do that?
edit: Added second table.
assuming days is unique for every id.
SELECT id
FROM workdays
WHERE days IN ('mon', 'tue')
GROUP BY id
HAVING COUNT(*) = 2
otherwise, you need to have DISTINCT in HAVING clause to count only unique values.
HAVING COUNT(DISTINCT days) = 2

Fetching Total Sale of each day and month from database

I have table with column c_date as datetime, total as int type in mysql, and i want to print out sale of each day, and total sale of each month, and total sale annually including day, month, year where there was no sale.
Currently for daily sale, I am running below query :
mysql> select date(c_date) as date, sum(total) as total_sale from sale group by date;
+------------+------------+
| date | total_sale |
+------------+------------+
| 2013-10-3 | 798 |
| 2013-10-6 | 114 |
+------------+------------+
but, i want something like this :
mysql> select date(c_date) as date, sum(total) as total_sale from sale group by date;
+------------+------------+
| date | total_sale |
+------------+------------+
| 2013-10-1 | 0 |
| 2013-10-2 | 0 |
| 2013-10-3 | 798 |
| 2013-10-4 | 0 |
| 2013-10-5 | 0 |
| 2013-10-6 | 114 |
+------------+------------+
and for Monthly, I am getting this :
mysql> select c_date, month(c_date) as month, year(c_date) as year, sum(total) as total from sale group by c_date order by c_date;
+---------------------+-------+------+-------+
| c_date | month | year | total |
+---------------------+-------+------+-------+
| 2013-10-3 02:40:06 | 10 | 2013 | 228 |
| 2013-10-3 02:41:58 | 10 | 2013 | 114 |
| 2013-10-3 02:44:36 | 10 | 2013 | 114 |
| 2013-10-3 02:46:40 | 10 | 2013 | 114 |
| 2013-10-3 02:49:15 | 10 | 2013 | 114 |
| 2013-10-3 02:53:36 | 10 | 2013 | 114 |
| 2013-10-6 07:43:27 | 10 | 2013 | 114 |
+---------------------+-------+------+-------+
But i want something like this :
mysql> select c_date, month(c_date) as month, year(c_date) as year, sum(total) as total from sale group by c_date order by c_date;
+---------------------+-------+------+-------+
| c_date | month | year | total |
+---------------------+-------+------+-------+
| 2013-1-3 02:40:06 | 1 | 2013 | 0 |
| 2013-2-3 02:41:58 | 2 | 2013 | 0 |
| 2013-3-3 02:44:36 | 3 | 2013 | 0 |
| 2013-4-3 02:46:40 | 4 | 2013 | 0 |
| 2013-5-3 02:49:15 | 5 | 2013 | 0 |
| 2013-6-3 02:53:36 | 6 | 2013 | 0 |
| 2013-7-6 07:43:27 | 7 | 2013 | 0 |
| 2013-8-3 02:44:36 | 8 | 2013 | 0 |
| 2013-9-3 02:46:40 | 9 | 2013 | 0 |
| 2013-10-3 02:49:15 | 10 | 2013 | 912 |
| 2013-11-3 02:53:36 | 11 | 2013 | 0 |
| 2013-12-6 07:43:27 | 12 | 2013 | 0 |
+---------------------+-------+------+-------+
Is this possible with MysqL ?
Since it's impossible to use sequences in MySQL (actually, they simply do not exist there), you'll have to create your dates range table first. That will be like:
CREATE TABLE dates_range (record_date DATE)
and then fill this table with dates, starting from minimum among dates, that exist in your sale table and till maximum.
After this, using SQL LEFT JOIN operator, you'll be able to aggregate your data like this:
SELECT
YEAR(dates_range.record_date),
MONTH(dates_range.record_date),
DAY(dates_range.record_date),
COALESCE(SUM(sale.total), 0) AS total_sum
FROM
dates_range
LEFT JOIN sale
ON dates_range.record_date=DATE(sale.c_date)
GROUP BY
YEAR(dates_range.record_date),
MONTH(dates_range.record_date),
DAY(dates_range.record_date)
it looks to me that you need an outer join with a calendar table.
Imagine a calendar table populated like:
Calendar
Year Month Day
2013 201310 2013-10-1
2013 201310 2013-10-2
...
Then you can write a query like
select date(c_day) as date,
sum(total) as total_sale
from calendar c
left outer join sale s
on c.day = s.c_date
where c.month = 201310
group by c_day
having c_day <= max(s.c_date); -- this is to avoid to show all
-- days for October

Get time difference for each row in table

I am working on an online time card system and have ran into a road block. What I need to do is calculate in each row the timeIn and timeOut for a date the employee might clock in and out several times a day. I have a working query to find the total for the entire day but not for each individual row. I have included the structure of the database table with some examples of what I would like to see.
+----+------------+----------+---------+------------------------------+-------------+------------+-----------+----------+
| id | employeeID | date | timeIn | jobDescription | equipType | unitNumber | unitHours | timeOut |
+----+------------+----------+---------+------------------------------+-------------+------------+-----------+----------+
| 8 | 1 | 01/15/13 | 7:00 AM | Loaded sand in Jefferson | Excavator | 345 | NULL | 9:30 PM |
| 9 | 1 | 01/15/13 | 10:00 AM | Loaded sand in Jefferson | Excavator | 345 | NULL | 12:00 PM |
| 10 | 1 | 01/16/13 | 7:00 AM | Loaded sand in Jefferson | Excavator | 345 | NULL | 5:30 PM |
| 11 | 1 | 01/17/13 | 7:00 AM | Loaded sand in Jefferson | Excavator | 345 | NULL | 5:30 PM |
| 12 | 1 | 01/18/13 | 8:00 AM | Backfill in Whispering Creek | Skid Loader | 297 | NULL | 5:30 PM |
| 13 | 1 | 01/19/13 | 8:00 AM | Backfill in Whispering Creek | Skid Loader | 297 | NULL | 3:30 PM |
| 1 | 1 | 01/20/13 | 6:00 | | Excavator | 01E | 7238 | 17:00 |
| 2 | 1 | 01/21/13 | 6:00 | Worked in Jefferson | Excavator | 01E | 7238 | 17:00 |
| 3 | 1 | 01/22/13 | 6:00 | Worked in Jefferson | Excavator | 02E | 7238 | 17:30 |
| 4 | 1 | 01/23/13 | 6:00 | Worked in Whispering Creek | Skid Loader | 32SL | 2338 | 18:30 |
| 5 | 1 | 01/24/13 | 8:00 | Worked in Hubbard | Scraper | 54C | 9638 | 11:30 |
| 6 | 1 | 01/25/13 | 8:00 | Worked in Jefferson | Dozer | 4D | 941 | 19:30 |
| 7 | 1 | 01/26/13 | 8:00 | Pushed Snow | Loader | 950H | 342 | 20:30 |
+----+------------+----------+---------+------------------------------+-------------+------------+-----------+----------+
Ok so what I would like to see is that for example the date 01/15/13 appears twice with different timeIn and timeOut values I would like to get a value back saying that in row with the id 8 there was 2:30 hours, then get another value back saying that in the row where id is 9 there was 2:00 hours. I would like to accomplish this with one query if possible.
This is my query to get the time for the entire day:
SELECT `employeeID`, SEC_TO_TIME(SUM(TIME_TO_SEC(TIMEDIFF(`timeOut`, `timeIn`)))) AS `totalTime` FROM `timeRecords` WHERE `date` = "01/15/13" AND `employeeID` = 1 GROUP BY `employeeID`;
If I understand you correctly you need this?
SELECT `employeeID`, TIMEDIFF(`timeOut`, `timeIn`) AS `totalTime` FROM `timeRecords`;
You can use PDO query to query your database which returns result set as array of associative array. For better performance you can use PDO prepare/execute.
<?php
function getTimeByRow($connection) {
$sql = "SELECT `employeeID`, TIMEDIFF(`timeOut`, `timeIn`) AS `totalTime` FROM `timeRecords`";
foreach ($connection->query($sql) as $row) {
print $row['employeeID'] . "\t";
print $row['totalTime'] . "\n";
}
}
?>
So you want to do something like this:
select employeeID, date, TIMEDIFF(timeout, timein) from timeRecords where date = x and employeeID = y