mysql list data excluding weekends - mysql

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

Related

SQL sum and show row with non-existent sum values

i have 2 tables : dt_user and dt_invoice.
**dt_members :**
id firstname
3 Salim
5 Sara
8 Julie
**dt_invoice**
user_id amount_ht period month year
3 4950 04 2018 04 2018
3 7200 10 2018 10 2018
8 11000 10 2018 10 2018
8 5500 11 2018 11 2018
3 6750 11 2018 11 2018
3 8700 12 2018 12 2018
3 8800 01 2019 01 2019
8 7500 01 2019 01 2019
3 4950 02 2019 02 2019
3 7550 03 2019 03 2019
I want to create a query joining the two table, but i want to show each user_id for PERIOD that there is in table dt_invoice.
**Expected results :**
user_id amount_ht period month year
3 4950 04 2018 04 2018
5 0 04 2018 04 2018 //non-existent record in dt_invoice
8 0 04 2018 04 2018 //non-existent record in dt_invoice
3 7200 10 2018 10 2018
5 0 10 2018 10 2018 //non-existent record in dt_invoice
8 11000 10 2018 10 2018
8 5500 11 2018 11 2018
5 0 11 2018 11 2018 //etc ...
3 6750 11 2018 11 2018
3 8700 12 2018 12 2018
5 0 12 2018 12 2018
8 0 12 2018 12 2018
3 8800 01 2019 01 2019
5 0 01 2019 01 2019
8 7500 01 2019 01 2019
3 4950 02 2019 02 2019
5 0 02 2019 02 2018
8 0 02 2019 02 2018
3 7550 03 2019 03 2019
5 0 03 2019 03 2018
8 0 03 2019 03 2018
Thanks in advance for your help, i'm totally stuck ..
SQL datas available here : https://rextester.com/live/LBSEY76360
also in sqlfiddle : http://sqlfiddle.com/#!9/728af3/1
Use a cross join to generate the rows and left join to bring in the values:
select m.user_id, p.period, p.month, p.year,
coalesce(t.amount_ht, 0) as amount_ht
from dt_members m cross join
(select distinct period, month, year from dt_invoice) p left join
dt_invoice t
on t.user_id = m.id and t.period = p.period;
Maybe this would help.
SELECT user_id, amount_ht, period, month, year
FROM dt_invoice
LEFT JOIN dt_members ON user_id = id

How to get timestamp to a specific day in 2 weeks

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.

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.

Get data from table where date between given date and 1 week back

I have database dbadmin, table - tbl_empreimburse with fields-emp_id,rem_amount,rem_date.
I want to retrieve data which comes from given date to a week back.
I tried this query,
SELECT SUM(rem_amount),DATEADD(dd, -7, "2012-01-10")
FROM tbl_empreimburse
GROUP BY emp_id
HAVING emp_id='5' AND rem_date BETWEEN DATEADD(dd, -7, "2012-01-10") AND "2012-01-10"
It gives me error "FUNCTION dbadmin.DATEADD does not exist". Do I need to convert "2012-01-10" to date format? Any Help, Please?
Try this:
This query gives result as you have specified for employee id 5 and date period of 7 days.
SELECT emp_id, SUM(rem_amount)
FROM tbl_empreimburse
WHERE emp_id='5' AND DATEDIFF('2012-12-31', rem_date) BETWEEN 0 AND 7;
OR
Below query gives you all employee data.
SELECT emp_id, SUM(rem_amount)
FROM tbl_empreimburse
GROUP BY emp_id
HAVING DATEDIFF('2012-12-31', rem_date) BETWEEN 0 AND 7;
Check this *SQLFIDDLE reference out. :)
I am not sure why you are using group by clause here...
Sample date:
ID AMOUNT RDATE
1 3400 January, 01 2012 00:00:00+0000
2 5000 January, 10 2012 00:00:00+0000
3 3000 January, 02 2012 00:00:00+0000
5 1000 January, 05 2012 00:00:00+0000
5 2000 January, 04 2012 00:00:00+0000
2 2000 February, 10 2012 00:00:00+0000
Query:
select * from emp
where id = 5;
here is the query to get sum
select id, sum(amount)
from emp
where rdate between '2012-01-10' - interval 7 day
and '2012-01-10'
and id = 5
;
Results:
all records by employee id = 5
ID AMOUNT RDATE
5 1000 January, 05 2012 00:00:00+0000
5 2000 January, 04 2012 00:00:00+0000
sum of amount by employee id = 5
ID SUM(AMOUNT)
5 3000

MySQL - Compare total this week against same week last year

How would I get a sum of sales totals for the current week against the same week last year?
There are two possible scenarios related to how the dates are stored, as below:
Scenario 1
**Sales**
Date Sales
-----------------------
2012-08-10 11040.00
2012-08-09 11500.00
2012-08-08 14060.00
2012-08-07 93000.00
2012-08-06 11200.00
...
2011-08-10 11040.00
2011-08-09 11500.00
2011-08-08 14060.00
2011-08-07 93000.00
2011-08-06 11200.00
Scenario 2
**Sales**
year month day Sales
---------------------------------------------
2012 08 10 11040.00
2012 08 09 11500.00
2012 08 08 14060.00
2012 08 07 23000.00
2012 08 06 11200.00
...
2011 08 10 13040.00
2011 08 09 11500.00
2011 08 08 12060.00
2011 08 07 33000.00
2011 08 06 11250.00
For your first scenario, join against the same table on the WEEKOFYEAR() and one added to last year's YEAR():
SELECT
YEARWEEK(thisyear.Date) AS `YearWeek`
SUM(lastyear.Sales) AS LastYearSales
SUM(thisyear.Sales) AS ThisYearSales
FROM
Sales thisyear
LEFT JOIN Sales lastyear ON
WEEKOFYEAR(thisyear.Date) = WEEKOFYEAR(lastyear.Date)
AND YEAR(thisyear.Date) = (YEAR(lastyear.Date) + 1)
GROUP BY `YearWeek`
The second scenario requires building a date out of the 3 separate values. I think this will work:
SELECT
YEARWEEK(CONCAT_WS('-', thisyear.year, thisyear.month, thisyear.day)) AS `YearWeek`,
SUM(lastyear.Sales) AS LastYearSales,
SUM(thisyear.Sales) AS ThisYearSales
FROM
Sales thisyear
LEFT JOIN Sales lastyear ON
WEEKOFYEAR(CONCAT_WS('-', thisyear.year, thisyear.month, thisyear.day)) = WEEKOFYEAR(CONCAT_WS('-', lastyear.year + 1, lastyear.month, lastyear.day))
GROUP BY `YearWeek`