I have got the query which will give me all the dates which are Monday and Tuesday
SELECT a.Date AS dat_e FROM ( SELECT DATE_ADD( '2018-01-17' , INTERVAL (1) DAY ) + INTERVAL( a.a + ( 10 * b.a ) + ( 100 * c.a ) ) DAY AS DATE FROM ( SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 ) AS a CROSS JOIN ( SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 ) AS b CROSS JOIN ( SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 ) AS c )a HAVING DAYOFWEEK(dat_e) IN ( 2,3)
I want to get the dates after 'x' weeks, ie: after 1,2 or 3 weeks. and the dates should be Monday and Tuesday
Related
I want week list with week number, week start date and end date between two dates. Let me give you an example,
If I am passing start date as 2019-12-11 and end date as 2019-12-25, then expected output should look like below:
Week Number | Week start date | Week end date
W1 2019-12-11 2019-12-14
W2 2019-12-15 2019-12-21
W3 2019-12-22 2019-12-25
I have tried using below query but I got output like
Week start date | Week end date
2019-12-15 2019-12-21
2019-12-22 2019-12-28
select start_date, date_add(start_date, INTERVAL 6 DAY) as end_date
from
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) start_date
from
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 i union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
where start_date between '2019-12-11' and '2019-12-25'
AND date_format(start_date, '%w') = 0
You can use the following solution using WEEK function and ROW_NUMBER:
-- calendar table: https://stackoverflow.com/a/45992247/3840840
SELECT CONCAT('W', ROW_NUMBER() OVER (ORDER BY WEEK(start_date))) AS `Week Number`,
MIN(start_date) AS `Week start date`, MAX(start_date) AS `Week end date`
FROM (
SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS start_date
FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
) v
WHERE start_date BETWEEN '2019-12-11' AND '2019-12-25'
GROUP BY WEEK(start_date)
ORDER BY WEEK(start_date)
By using WEEK you don't have to calculate the weeks yourself. MySQL can detect the weeks. With WEEK you can get the week number of a date value. You can group by this week number to get the rows for every week. With MIN and MAX on the date value you get the first and last date of each week.
With ROW_NUMBER you can add a row number to your result. This function is available since MySQL 8.0. On earlier versions of MySQL you can use a solution like the following:
SELECT CONCAT('W', #row_number:=#row_number+1) AS `Week Number`,
MIN(start_date) AS `Week start date`, MAX(start_date) AS `Week end date`
FROM (
SELECT ADDDATE('1970-01-01', t4 * 10000 + t3 * 1000 + t2 * 100 + t1 * 10 + t0) AS start_date
FROM
(SELECT 0 t0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t0,
(SELECT 0 t1 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t1,
(SELECT 0 t2 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t2,
(SELECT 0 t3 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t3,
(SELECT 0 t4 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9) t4
ORDER BY start_date
) v, (SELECT #row_number:=0) rn
WHERE start_date BETWEEN '2019-12-11' AND '2019-12-25'
GROUP BY WEEK(start_date)
ORDER BY WEEK(start_date)
demo on dbfiddle.uk
I want to get the Mondays between two dates with a select statement, but I only have searched in sql server.
I have tried this, but it doesn´t work:
SELECT DATE_ADD('2017-01-01', INTERVAL ROW DAY) AS Date
FROM (
SELECT #row := #row + 1 AS row
FROM (
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6
) t1,
(
SELECT 0 UNION ALL
SELECT 1 UNION ALL
SELECT 3 UNION ALL
SELECT 4 UNION ALL
SELECT 5 UNION ALL
SELECT 6
) t2,
(
SELECT #row:=-1
) t3 LIMIT 31
) b
WHERE DATE_ADD('2017-01-01', INTERVAL ROW DAY) BETWEEN '2017-01-01' AND '2017-12-31'
AND DAYOFWEEK(DATE_ADD('2017-01-01', INTERVAL ROW DAY)) = 2
This query only gives me the Monday´s date for one month.
I hope that you can help me
Regards!
If you really want to solve this SQL only, you have to delve a bit deeper and generate a sequence of days, this is by far the most difficult side task to solve this. Besides this, as you have already guessed, you can use DAYOFWEEK or WEEKDAY to get your desired days.
SELECT *
FROM (
SELECT DATE_ADD('2013-01-01',
INTERVAL n4.num*1000+n3.num*100+n2.num*10+n1.num DAY ) AS DATE
FROM (
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n1,
(
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n2,
(
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n3,
(
SELECT 0 AS num
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
) AS n4
) AS a
WHERE DATE >= '2017-01-01' AND DATE < NOW()
AND WEEKDAY(DATE) = 0
ORDER BY DATE
Some other RDBMS have inbuild functions for that.
If would be way easier if you have a calendar table where all dates are already present.
I think that this solution will work with better performance than previous
SET #date_start = date('2019-07-06');
SET #date_end = date('2019-09-18');
SELECT CASE WHEN MOD(DAYOFWEEK(#date_start), 7) <= 2 AND
MOD(DAYOFWEEK(#date_start), 7) + DATEDIFF(v.selected_date, #date_start) - 7 * FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) >= 2 OR
MOD(DAYOFWEEK(#date_start), 7) > 2 AND
MOD(DAYOFWEEK(#date_start), 7) + DATEDIFF(v.selected_date, #date_start) - 7 * FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) >= 9 THEN 1 ELSE 0 END
+ FLOOR(DATEDIFF(v.selected_date, #date_start) / 7) num_of_mo
, #date_start start_date,v.selected_date end_date
FROM (select adddate(#date_start,t4*10000 + t3*1000 + t2*100 + t1*10 + t0) selected_date from
(select 0 t0 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t0,
(select 0 t1 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t1,
(select 0 t2 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t2,
(select 0 t3 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t3,
(select 0 t4 union select 1 union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9) t4) v
WHERE v.selected_date <= #date_end;
I need to generate the days between two dates in sql like this:
generate days from date range
Im using this query:
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
Works well but this generates always 1000 days. How can i generate any other number of days like 365?
You could add a limit clause (and an order by)
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all
select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all
select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all
select 3 union all select 4 union all select 5 union all
select 6 union all select 7 union all select 8 union all
select 9) as c
) a
order by 1 desc
limit 365
Or, if you are allowed to create temporary tables, in a more readable fashion - and extendable to 10,000 integers or more quite easily:
CREATE TEMPORARY TABLE units(idx)
ENGINE=MEMORY
AS (
SELECT 0
UNION ALL SELECT 1
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
);
SELECT a.the_date
FROM (
SELECT curdate() - INTERVAL (hundreds + tens + units) DAY AS the_date
FROM (SELECT idx AS units FROM units) units
CROSS JOIN (SELECT idx* 10 AS tens FROM units) tens
CROSS JOIN (SELECT idx* 100 AS hundreds FROM units) hundreds
WHERE hundreds + tens + units < 365
) AS a
ORDER BY 1
;
SELECT
floor(
datediff('2016-08-01','2016-07-01') / 7) * 2 + (
CASE WHEN
IF (weekday('2016-08-01') >= 5, 4,weekday('2016-08-01')) >=
IF (weekday('2016-07-02') >= 5, 4,weekday('2016-07-01'))
THEN
IF (weekday('2016-08-01') >= 5, 4,weekday('2016-08-01')) -
IF (weekday('2016-07-01') >= 5, 4,weekday('2016-07-01'))
ELSE
5 +
IF (weekday('2016-08-01') >= 5, 4,weekday('2016-08-01')) -
IF (weekday('2016-07-01') >= 5, 4, weekday('2016-07-01'))
END
) weekdays;
when i execute this code it always return 9 i don't know where i am doing mistake please suggest me where am doing wrong. while between Saturday and Sunday between given date should be 10 please suggest me
If you don't have a table having all the dates between your start date and end date (inclusive) then you need to adopt a query which will create all the dates between your given date range (inclusive) first. Then use WEEKDAY function of MySQL to check whether the day is Saturday or Sunday
SELECT
dateTable.Day,
DAYNAME(dateTable.Day) AS dayName
FROM
( SELECT ADDDATE('2016-07-01', INTERVAL #i:=#i+1 DAY) AS DAY
FROM (
SELECT a.a
FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
) a
JOIN (SELECT #i := -1) r1
WHERE
#i < DATEDIFF('2016-08-01', '2016-07-01')
) AS dateTable
WHERE WEEKDAY(dateTable.Day) IN (5,6)
ORDER BY dateTable.Day;
WORKING DEMO
Note:
WEEKDAY returns the weekday index for date (0 = Monday, 1 = Tuesday, … 6 = Sunday).
EDIT:
If you need only count:
SELECT
COUNT(*) AS total
FROM
( SELECT ADDDATE('2016-07-01', INTERVAL #i:=#i+1 DAY) AS DAY
FROM (
SELECT a.a
FROM (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS a
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS b
CROSS JOIN (SELECT 0 AS a UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9) AS c
) a
JOIN (SELECT #i := -1) r1
WHERE
#i < DATEDIFF('2016-08-01', '2016-07-01')
) AS dateTable
WHERE WEEKDAY(dateTable.Day) IN (5,6)
Demo
I need to convert this query from MySQL format to SQLite. I'm trying myself but I've found some difficulty.
In SQLite, the curdate() and the interval functions do not exist.
select a.Date
from (
select curdate() - INTERVAL (a.a + (10 * b.a) + (100 * c.a)) DAY as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as a
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as b
cross join (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9) as c
) a
where a.Date between '2010-01-20' and '2010-01-24'
What this query actually does is just generating lots of consecutive dates (up to one thousand previous days).
In SQLite 3.8.3 or later, this can be done more easily with a recursive common table expression:
WITH RECURSIVE dates(d)
AS (VALUES('2010-01-20')
UNION ALL
SELECT date(d, '+1 day')
FROM dates
WHERE d < '2010-01-24')
SELECT d AS date FROM dates;
Here is the basic syntax:
select a.Date
from (select date('now', '-'||(a.a + (10 * b.a) + (100 * c.a))|| ' days') as Date
from (select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9
) a cross join
(select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9
) b cross join
(select 0 as a union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6 union all select 7 union all select 8 union all select 9
) c
) a;
I left out the where clause because those dates are more than 1000 days in the past, so they won't select anything anyway.