Problem
I want to show all users for a specific range lets say from 2020-01-01 to from 2020-01-05.
I have a table user where all users are saved. Imagine following table:
user
id | createdAt
1 2020-01-01
2 2020-01-02
3 2020-01-03
4 2020-01-03
5 2020-01-05
The outcome should be (relating to the above user table):
date | count
2020-01-01 1
2020-01-02 2
2020-01-03 4
2020-01-04 4
2020-01-05 5
What I have so far
I have a query that returns the example above as needed:
SELECT COALESCE((SELECT COUNT(*) FROM user u WHERE DATE(u.createdAt) <= DATE(dates.gen_date) AND u.role = 'USER' GROUP BY dates.gen_date ),0) AS y, dates.gen_date AS x FROM user u, (select * from
(select adddate('1970-01-01',t4*10000 + t3*1000 + t2*100 + t1*10 + t0) gen_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 gen_date between DATE(?) and DATE(?)) AS dates GROUP BY x;
But the execution of this statement is really slow by huge number of users and a large time range.
I thought also of a materialized view but this would be only the last way out.
Database used: MySql 5.7
Test
SELECT (dates.mindate + INTERVAL (t0.n+10*t1.n+100*t2.n+1000*t3.n) DAY) `date`,
COUNT(users.id) `count`
FROM users,
(SELECT ? mindate, ? maxdate) dates,
(select 0 n 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 n 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 n 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 n union select 1 union select 2) t3
WHERE users.createdAt <= (dates.mindate + INTERVAL (t0.n+10*t1.n+100*t2.n+1000*t3.n) DAY)
GROUP BY `date`
HAVING `date` <= dates.maxdate
ORDER BY `date`
It must be less expensive.
Related
I have the below table structure.
ID | FromDate | ToDate
1 | 2020-01-02 | 2020-06-01
2 | 2020-08-01 | 2020-12-01
3 | 2020-01-02 | 2020-11-28
4 | 2020-04-01 | 2020-05-28
When I pass 2 input parameters named fromDate and toDate, it should select the relevant records.
E.g. If FromDate = 2020-01-01 and ToDate = 2020-06-01, it should return records with IDs 1 and 4 since those two records are between the dates as the parameters supplied.
I am using the below method at the moment and I feel like it's wasting a lot of resources.
AND ToDate IN (select * from
(select adddate('2000-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_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 selected_date between '2021-01-02 00:00:00' and '2022-03-02 00:00:00') ORDER BY name ASC,lt.ID ASC<code>
Is there any other way to achieve this task?
select * from table_name where fromDate>'2020-xx-xx' AND ToDate<'2020-xx-xx';
this query format can get records between insertion dates
I have a table which contains two columns: date, and revenues generated in this date, however, if no revenues were generated at a certain date, this date will not show in the table, what I want is to show this date with 0 as revenue.
I tried a query that generates a list of dates between two dates, however, I couldn't find how to left join this query with my table since this date generator query has no id.
this is my table query:
SELECT CAST(insertDate AS DATE) AS DATE,
SUM(timeofcall)*10 as total_Revenue_Generated_from_CallBacks
FROM callcompletion.tbl_calltracking
GROUP BY CAST(insertDate AS DATE);
results->
DATE total_Revenue_Generated_from_CallBacks
2019-10-14 2200
2019-10-15 44000
2019-10-16 4400
2019-10-17 8800
2019-10-24 12100
and this is the date generator query:
SELECT selected_date FROM (
SELECT adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_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 selected_date BETWEEN '2019-10-14' AND '2019-10-24'
results->
selected_date
2019-10-14
2019-10-15
2019-10-16
2019-10-17
2019-10-18
2019-10-19
2019-10-20
2019-10-21
2019-10-22
2019-10-23
2019-10-24
expected results:
DATE total_Revenue_Generated_from_CallBacks
2019-10-14 2200
2019-10-15 44000
2019-10-16 4400
2019-10-17 8800
2019-10-18 0
2019-10-19 0
2019-10-20 0
2019-10-21 0
2019-10-22 0
2019-10-23 0
2019-10-24 12100
You need to decide what is the minimum and maximum date you wish to show. In addition to that, you can simply join the generated dates with your original query:
SELECT d.selected_date AS DATE, ifnull(SUM(c.timeofcall)*10,0) as total_Revenue_Generated_from_CallBacks
FROM (
SELECT adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) selected_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
) as d
left join callcompletion.tbl_calltracking c on CAST(c.insertDate AS DATE) = d.selected_date
WHERE d.selected_date between '2019-10-14' and '2019-10-24'
GROUP BY d.selected_date;
See DB-Fiddle
Currently having a little difficulty with respect to getting a list of dates.
I currently have the following SQL:
SELECT DISTINCT DATE(startDate) activity_date
, CASE WHEN (DATE(endDate) - DATE(startDate)) > 0 THEN DATE(endDate) ELSE FALSE END multiEvent
FROM activities
WHERE startdate BETWEEN '2017-08-01' AND '2017-08-31'
AND accountid = 578
ORDER
BY DATE(startdate)
Which gives the following result:
activity_date | multiEvent
2017-08-07 | 0
2017-08-07 | 2017-08-10
2017-08-18 | 0
However, what i am trying to achieve is, if multiEvent is not zero, then list the dates between the dates of activity_date & multiEvent into a single column.
Result I am trying to achieve:
activity_date |
2017-08-07 |
2017-08-07 |
2017-08-08 |
2017-08-09 |
2017-08-10 |
2017-08-18 |
ideas? :)
You need to first find a way to create rows for dates between activity_date and multiEvent. This query will produce the intended resultset of dates, as individual rows.
select date(eachDate) as eachDate from
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) as eachDate
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) as v
where
eachDate between date('2017-08-07')
and date('2017-08-10') order by eachDate asc ;
This will produce a result like
eachDate
2017-08-07
2017-08-08
2017-08-09
2017-08-10
Now, we need to fit in the above query with your existing query to get the intended output. The query would look something like this.
select
activity_date
from
(select
date(startDate) as activity_date
from
activities
where
startdate between date('2017-08-01') and date('2017-08-31')
and accountid = 578
and NOT (DATE(endDate) - DATE(startDate)) > 0
union all
select
eachDate
from
(select date(eachDate) as eachDate
from
(select adddate('1970-01-01',t4.i*10000 + t3.i*1000 + t2.i*100 + t1.i*10 + t0.i) as eachDate
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) as v
where
eachDate between date('2017-08-01')
and date('2017-08-31')) as dates_table
join
(select
date(startDate) as startDate,
date(endDate) as endDate
from
activities
where
startdate between date('2017-08-01') and date('2017-08-31')
and accountid = 578
and (date(endDate) - date(startDate)) > 0 ) as activities_table
on dates_table.eachDate between activities_table.startDate and activities_table.endDate) as main
order by
main.activity_date asc;
and the output looks like this.
activity_date
2017-08-07
2017-08-07
2017-08-08
2017-08-09
2017-08-10
2017-08-18
I have a date range parameter, need to split into multiple date, and each will have same time as the parameter.
Not sure what is the problem with ADDTIME, maybe Im missing a cast? I can solve it casting to string and concat but I guess should be easier.
Current Output
selectDate time(#s_date) time(#e_date) addtime(date(a.selectDate), time(#s_date))
1 2016-09-03 08:00:00 16:00:00 08:00:00
2 2016-09-04 08:00:00 16:00:00 08:00:00
Desire Output
selectDate time(#s_date) time(#e_date) addtime(date(a.selectDate), time(#s_date))
1 2016-09-03 08:00:00 16:00:00 2016-09-03 08:00:00
2 2016-09-04 08:00:00 16:00:00 2016-09-04 08:00:00
Possible solution:
CONCAT(DATE_FORMAT(a.selectDate, '%Y-%m-%d '),
DATE_FORMAT(#s_date, '%H:%i:%s')) as start_time,
My big query
select a.selectDate,
time(#s_date),
time(#e_date),
addtime(date(a.selectDate), time(#s_date))
from (
select '1900-01-01' + INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) DAY as selectDate
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
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 d
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 e
) a
CROSS JOIN (SELECT #s_date := '2016-09-03 08:00:00', #e_date := '2016-09-04 16:00:00') par
WHERE selectDate BETWEEN date(#s_date)
AND date(#e_date)
select a.selectDate,
time(#s_date),
time(#e_date),
addtime(concat(a.selectDate,' ','00:00:00'),time(#s_date))
from (
select '1900-01-01' + INTERVAL (a.a + (10 * b.a) + (100 * c.a) + (1000 * d.a) + (10000 * e.a)) DAY as selectDate
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
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 d
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 e
) a
CROSS JOIN (SELECT #s_date := '2016-09-03 08:00:00', #e_date := '2016-09-04 16:00:00') par
WHERE selectDate BETWEEN date(#s_date)
AND date(#e_date)
refer this link
I want to display all the dates between two dates for a particular record
And this is the table :
ID Start_Date End_Date
1 2013-01-14 2013-01-18
2 2013-02-01 2013-02-04
and now i want to get all the dates between from date and to date.
Expected output
ID Date
1 2013-01-14
1 2013-01-15
1 2013-01-16
1 2013-01-17
1 2013-01-18
2 2013-02-01
2 2013-02-02
2 2013-02-03
2 2013-02-04
guide me to write query for that with out creating any extra tables.
I have already tried this following query
select * from
(select adddate('1970-01-01',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 selected_date between '2012-02-10' and '2012-02-15'
its working fine for single record. but i want get all the date intervals from my table
Updated
i have 6 qty of chairs for all days. So one user book 3 chars on 2013-01-14 to 2013-01-18 another person book 2 chars on 2013-01-17 to 2013-01-20. So my expected output shown below.
ID Date Available
1 2013-01-14 3
1 2013-01-15 3
1 2013-01-16 3
1 2013-01-17 5
1 2013-01-18 5
1 2013-01-19 2
1 2013-01-20 2
1 2013-01-21 2
How about
select
t.id,
DATE_FORMAT(a.Date,'%Y-%m-%d') as 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
join test t on a.Date between t.Start_Date and t.End_Date
order by t.id,Date
DEMO
First, I don't know your specific use case, but this feels ripe for more optimization. However, how about this?
select * from
(select adddate('1970-01-01',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 (selected_date between '2012-02-10' and '2012-02-15') OR
(selected_date between '2012-03-10' and '2012-03-15') OR
(selected_date between '2012-04-10' and '2012-04-15')