简体   繁体   中英

MySQL - Find number of days in date range which fall in a given month

I have a table which shows jobs worked by people over a date range (which is always a maximum of 5 days).

Is it possible to break down the contents of a date range by month?

My table (simplified) looks like this:

+---------------------+---------------------+--------------+
| datefrom            | dateto              | dailypayrate |
+---------------------+---------------------+--------------+
| 2014-05-05 00:00:00 | 2014-05-10 00:00:00 |        78.00 |
| 2014-04-07 00:00:00 | 2014-04-14 00:00:00 |        59.30 |
| 2014-02-10 00:00:00 | 2014-02-14 00:00:00 |        82.66 |
| 2014-04-28 00:00:00 | 2014-05-02 00:00:00 |        91.00 |<-- !
| 2014-01-28 00:00:00 | 2014-01-31 00:00:00 |        65.00 |
+---------------------+---------------------+--------------+

I would like to show the total paid per row in a given month eg in the case of row 4 for April, it would show 273 which is the dailypayrate of 91 multiplied by the 3 days worked in April (even though the row shows 5 days).

Well, I don't know if this is a complete solution, but it's a start...

SELECT *
     , (DATEDIFF(LEAST(LAST_DAY(datefrom),dateto),datefrom)+1)*dailypayrate x 
  FROM  
     my_table;
+---------------------+---------------------+--------------+--------+
| datefrom            | dateto              | dailypayrate | x      |
+---------------------+---------------------+--------------+--------+
| 2014-01-28 00:00:00 | 2014-01-31 00:00:00 |        65.00 | 260.00 |
| 2014-02-10 00:00:00 | 2014-02-14 00:00:00 |        82.66 | 413.30 |
| 2014-04-07 00:00:00 | 2014-04-14 00:00:00 |        59.30 | 474.40 |
| 2014-04-28 00:00:00 | 2014-05-02 00:00:00 |        91.00 | 273.00 |
| 2014-05-05 00:00:00 | 2014-05-10 00:00:00 |        78.00 | 468.00 |
+---------------------+---------------------+--------------+--------+

http://sqlfiddle.com/#!2/7c1cbb/1

You can do what you want in SQL but it's not very cute. It's very easy to count for the lines where the daterange doesn't include a month change (WHERE MONTH(timefrom) = MONTH(timeto)). Just do a DATEDIFF like suggested by Strawberry.

SELECT 
        MONTH(datefrom) as month_number, 
        DATEDIFF(dateto, datefrom) as days_worked, 
        DATEDIFF(dateto, datefrom)*dailypayrate as salary
FROM my_table
WHERE MONTH(datefrom) = MONTH(dateto)

For the daterange which contain a month change, we need to split these lines in two: one which will count for MONTH(timefrom), and the other for the MONTH(timeto). Here it is for the MONTH(timeto), the other one is simply a substraction.

SELECT 
        MONTH(dateto) as month_number, 
        MINUTE(dateto)/(60*24) + HOUR(dateto)/24 + DAY(dateto)-1 as days_worked, 
        (MINUTE(dateto)/(60*24) + HOUR(dateto)/24 + DAY(dateto)-1)*dailypayrate as salary
FROM my_table
WHERE MONTH(datefrom) != MONTH(dateto)

Then we UNION these 3 queries, group by month_number and it should give correct numbers.

http://sqlfiddle.com/#!2/120766/2

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM