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
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
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.
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
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')
I want to receive results like the sample output.
Listed each day beween two dates and the number of online posts from a company.
For example:
TABLE
id | online_From | online_To | comp_id
11 | 2014-04-02 | 2014-04-05 | 20
12 | 2014-04-11 | 2014-04-16 | 21
13 | 2014-04-03 | 2014-04-07 | 20
17 | 2014-04-29 | 2014-04-30 | 23
19 | 2014-04-04 | 2014-04-11 | 20
I want to receive:
SAMPLE OUTPUT
2014-04-01 | 0
2014-04-02 | 1
2014-04-03 | 2
2014-04-04 | 3
2014-04-05 | 3
2014-04-06 | 2
2014-04-07 | 2
2014-04-08 | 1
2014-04-09 | 1
2014-04-10 | 1
2014-04-11 | 1
2014-04-12 | 0
2014-04-13 | 0
…
2014-05-07 | 0
I used this mysql code to list the requested dates (and also split into y/m/d/w for generate charts):
select selected_date, year(selected_date) as y, day(selected_date) as d, week(selected_date) as w, month(selected_date) as m 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 '2014-04-01' and '2014-05-07'
GROUP BY y,m,d ORDER BY y ASC, m ASC, d ASC
2014-04-01|2014 |1 |14 |4 |0
2014-04-02|2014 |2 |14 |4 |1
2014-04-03|2014 |3 |14 |4 |2
…
This comes from: How to get list of dates between two dates in mysql select query
I tried a lot of things but I never became the hoped result.
I want to loop trough the dates and check the number of posts that where online that day.
Hopefully somebody can help me!
Thanks
This should get you started if you want a SQL-only answer. Have called your table comp_table...
select d.selected_date,d.d,d.m,d.y,
count(ct.id)
from
(
select selected_date, year(selected_date) as y, day(selected_date) as d, week(selected_date) as w, month(selected_date) as m 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 '2014-04-01' and '2014-05-07'
GROUP BY selected_date
) d
left outer join comp_table ct on d.selected_date between ct.online_From and ct.online_To
group by d.selected_date
order by 1 asc
;
You might be better off periodically populating an all_dates table to use in place of the inline view though. Would be more performant!
EDIT
If you want to maintain 'gimme all dates even if they have a 0 count' yet filter the results e.g. by the comp_id column then simply change the left outer join to include your filter by clause. For example:
select d.selected_date,d.d,d.m,d.y,
count(ct.id)
from
(
select selected_date, year(selected_date) as y, day(selected_date) as d, week(selected_date) as w, month(selected_date) as m 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 '2014-04-01' and '2014-05-07'
GROUP BY selected_date
) d
left outer join comp_table ct
on d.selected_date between ct.online_From and ct.online_To
and ct.comp_id = 20
group by d.selected_date
order by 1 asc
;
If you have not already installed it, I recommend you install common_schema. Once that's installed you can use the numbers table to simplify your query.
For example this query should give you the desired output:
select days.day,count(distinct your_table.id) from
(
select '2014-04-01' + interval n day AS day
from common_schema.numbers
having day between '2014-04-01' and '2014-05-07'
) days
left outer join your_table on your_table.online_From <= days.day and your_table.online_To >= days.day
group by days.day
order by days.day