SQL querying dates between dates in two columns - mysql

I have two tables which I want to perform a query on.
The first table Events has a column of events and a column of dates.
event | date
------------+------------
"Christmas" | 2019-12-25
"Blue moon" | 2020-05-16
"Earth day" | 2020-03-26
The second table Periods has a column with names of periods, and two columns with the start and end dates of the periods.
period | start date | end date
--------------------+-------------+-----------
"Shark week" | 2019-03-20 | 2019-03-27
"Easter weekend" | 2020-04-12 | 2020-04-15
"Ramadan" | 2020-04-20 | 2020-05-24
I want the query to return a list of events and dates from the Events table where the event occurs between the start and end date of any period.
The query would give the following result on the above tables:
event | date
------------+------------
"Blue moon" | 2020-05-16
"Earth day" | 2020-03-26
I have limited knowledge of SQL. The best I can do is to query the events table for events that occurred during a single period. Like this:
SELECT event, date FROM 'Events'
WHERE ("2019-03-20" < date) AND (date < "2019-03-27")
I have looked at related questions for querying between two dates. The related questions don't cover cases where the dates come from columns of a table.

This sounds like a join:
select e.*, p.*
from events e join
periods p
on e.date >= p.start_date and e.date <= p.end_date;

Related

With SQL I want to find a date BETWEEN 2 columns with LIKE

So I'm working on a site that uses MySQL and in the reminders table i have 3 columns called date, date_to, and yearly. The dates are stored as for example 2022-06-15.
If for example there is a yearly = 1 reminder with date and date_to being 2021-06-14 and 2021-06-16, how can i look BETWEEN date and date_to if I need to use LIKE because sometimes i need to use the -06-15 part because it's yearly = 1?
I need to use -06-15 sometimes because if its a yearly reminder, i cant just check on the year too because its meant to be repeated every year.
Table example:
| date | date_to | yearly |
| -----------| -------------- | ------ |
| 2021-06-14 | 2021-06-16 | 1 |
| 2022-05-03 | 2022-05-04 | 0 |
Expected output after searching for a yearly reminder for date 06-15:
| date | date_to | yearly |
| -----------| -------------- | ------ |
| 2021-06-14 | 2021-06-16 | 1 |
If I understand your issue correctly, you just want to check if your date is between a from date and a to_date of your table. This can basically be done with this query:
SELECT date_from, date_to, yearly
FROM yourtable
WHERE '2021-06-15' BETWEEN date_from AND date_to;
If you don't care about the year, but want to check the day only, you can use DATE_FORMAT like this:
SELECT date_from, date_to, yearly
FROM yourtable
WHERE DATE_FORMAT('2021-06-15', "%m-%d")
BETWEEN DATE_FORMAT(date_from, "%m-%d")
AND DATE_FORMAT(date_to, "%m-%d")
Then it doesn't matter which year appears (in this example, 2021), only the day will be checked.
It could also be mentioned that MYSQL also provides a function DAYOFYEAR which will work correctly in most cases for a query like this:
SELECT date_from, date_to, yearly
FROM yourtable
WHERE DAYOFYEAR('2021-06-15')
BETWEEN DAYOFYEAR(date_from) AND DAYOFYEAR(date_to);
This will also ignore the year and check the day only. It's a bit easier to read, but it's less safe because it could fail when a lag year is involved since then the day of year will be one more than in other years.
Please note I changed the name of "your" column "date" to "date_from" in my answer. This is no mistake, but I recommend to do not use SQL key words or function names as table name or column name. Furthermore, the column name "date_from" better points out the difference to the column "date_to", so you should rename the column if possible.

SQL get the time when user access the most

We have a list of page url and dateTime record on database.
Is it possible to get the hour where user have access it the most?
The column time displays what time users have access the url the most.
The expected result should look like these:
page URL | # visitor per day | Date | Max visitor/hour| time
----------+-------------------+--------------------+-----------------+--------------
www.url1 | 49 | 07/07/2017 | 23 | 12:00 - 13:00
www.url2 | 88 | 07/07/2017 | 39 | 7:00 - 8:00
In Subquery get the max hour per each URL and day.
Then join that to the main table, to get the required records.
If you need max hour irrespective of day, then just drop Date column from sub query and the join condition.
select *
from maintable
join
( select pageURL, Date, max(MaxVisitorPerHour) as maxhour
from table
group by pageURL, Date) subq
on
(maintable.pageURL=subq.pageURL AND maintable.Date=subq.Date and
maintable.maxVisitorPerHour=subq.maxhour)

MySQL data in 15 Minutes Increments

I am trying to create high charts time line graph for my school attendance but I get slightly different records appearing in my result.
The table that stores attendance is :
+++++++++++++++++++++++++++++++++
Id | Date | AttendTime(varchar)
--------------------------------
1 | 20160815 | 7:51
2 | 20160815 | 7:53
3 | 20160815 | 8:01
-------------------------------
I am using following sql to get the data
SELECT
COUNT(Id) as Total
FROM Attendance
WHERE Date = '20160815' AND
HOUR(STR_TO_DATE(AttendTime, '%H:%i')) <= HOUR(STR_TO_DATE('7:30', '%H:%i'))
And I should get 0 as there are none but I get 3 records. What am I doing wrong?
Thank you.
If you are simply trying to see how many attendances were before 7:30, you do not need the HOUR function:
SELECT
COUNT(Id) as Total
FROM Attendance
WHERE Date = '20160815'
AND STR_TO_DATE(AttendTime, '%H:%i') <= STR_TO_DATE('7:30', '%H:%i')

Graph per-day from ranges in MySQL

I am trying to make a graph that has a point for each day showing the number of horses present per-day.
This is example of data I have (MySQL)
horse_id | start_date | end_date |
1 | 2011-04-02 | 2011-04-03 |
2 | 2011-04-02 | NULL |
3 | 2011-04-04 | 2014-07-20 |
4 | 2012-05-11 | NULL
So a graph on that data should output one row per day starting on 2011-04-02 and ending on CURDATE, for each day it should return how many horses are registered.
I can't quite wrap my head around how I would do this, since I only have a start date and an end date for each item, and I want to know per-day how many was present on that day.
Right now, I do a loop and a SQL query per day, but that is - as you might have guesses - thousands of queries, and I was hoping it could be done smarter.
If a day between 2011-04-02 and now contains nothing, I still want it out but with a 0.
If possible I would like to avoid having a table with a row for each day containing a count.
I hope it makes sense, I am very stuck here.
What you should have, is a table containing just dates from at least the earliest date in your current table till the current date.
Then you can use this table to left join it something like this:
SELECT
dt.date,
COUNT(yt.horse_id)
FROM
dates_table dt
LEFT JOIN your_table yt ON dt.date BETWEEN yt.start_date AND COALESCE(end_date, CURDATE())
GROUP BY dt.date
Be sure to have a column of your_table in the COUNT() function, otherwise it counts the NULL values too.
The COALESCE() function returns the first of its parameter which isn't NULL, so if you don't have an end_date specified, the current date is taken instead.

Store multiple ranges in mysql table to make queries faster/easier

I have a data with multiple time ranges, for e.g. consider following columns
| from1 | to1 | from2 | to2 | from3 | to3 |
| 06:00 | 07:30 | 09:30 | 12:30 | 13:30 | 15:45 |
| 05:00 | 06:30 | 08:15 | 14:40 | 16:30 | 18:25 |
Now if I want to search for a time say 08:30, I would have to add 3 clauses in the query to match if the input occurs in range any out of all three from-to pairs.
In above case, it would return second row as 08:30 lies in the second from-to pair.
I want to know what would be the best practice to do this? It is ok even if I have to change my data model and not store those ranges in columns like I shown above. so that I can quickly and easily search through thousands of records
I can't think of a better alternative to this, please suggest.
I found this when i was searching for this problem.
It seems like your data model is not normalized. You should consider morjas suggestion about creating an additional table.
Below is a really ugly query that checks whether a date is in any of the three ranges, and then returns the matching rate.
select case
when date '2010-12-05' between range1_from and range1_to then range1_rate
when date '2010-12-05' between range2_from and range2_to then range2_rate
when date '2010-12-05' between range3_from and range3_to then range3_rate
end as rate
from events
where date '2010-12-05' between range1_from and range1_to
or date '2010-12-05' between range2_from and range2_to
or date '2010-12-05' between range3_from and range3_to;
ref.SQL query for finding a value in multiple ranges
Store your times as DATETIME and use BETWEEN
So:
where myDate BETWEEN '2011-03-18 08:30' AND '2011-09-18 09:00'