select records based on date - mysql

I have a table Employees with timestamp field createdAt and I want to run a query where I can select the employees that were created between 3 to 5 months from today date. So if
Employee A : 2016 - 01 - 28
Employee B : 2015 - 12 - 14 (less than 3 months from today)
Employee C : 2015 - 9 - 11 (more than 3 months but less than 5 months from today)
Employee D : 2015 - 01 - 20 (more than 5 months from today)
then my query should return only Employee C.
So far I have come up with this.
SELECT *
FROM employees
WHERE createdAt > NOW() - INTERVAL 2 Months AND createdAt < NOW() - INTERVAL 5 Months

start with lower date to higher. you can try this:
SELECT * FROM employees WHERE date(createdAt) between DATE_SUB(NOW(), INTERVAL 5 MONTH) and DATE_SUB(NOW(), INTERVAL 3 MONTH)

Related

MySQL Select data from table with dates between in reverse of interval 7 days

I have a MySQL requirement to select data from a table based on a start date and end date and group it by weekly also selecting the data in reverse order by date. Assume that, I have chosen the start date as 1st November and the end date as 04 December. Now, I would like to fetch the data as 04 December to 28 November, 27 November to 20 November, 19 November to 12 November and so on and sum the value count for that week.
Given an example table,
id
value
created_at
1
10
2021-10-11
2
13
2021-10-17
3
11
2021-10-25
4
8
2021-11-01
5
1
2021-11-10
6
4
2021-11-18
7
34
2021-11-25
8
17
2021-12-04
Now the result should be like 2021-12-04 to 2021-11-28 as one week, following the same in reverse order and summing the column value data for that week. I have tried in the query to add the interval of 7 days after the end date but it didn't work.
SELECT count(value) AS total, MIN(R.created_at)
FROM data_table AS D
WHERE D.created_at BETWEEN '2021-11-01' AND '2021-12-04' - INTERVAL 7 DAY ORDER BY D.created_at;
And it's also possible to have the last week may have lesser than 7 days.
Expected output:
end_interval
start_interval
total
2021-12-04
2021-11-27
17
2021-11-27
2021-11-20
34
2021-11-20
2021-11-13
4
2021-11-13
2021-11-06
1
2021-11-06
2021-10-30
8
2021-10-30
2021-10-25
11
Note that the last week is only 5 days depending upon the selected from and end dates.
One option to address this problem is to
generate a calendar of all your intervals, beginning from last date till first date, with a split of your choice, using a recursive query
joining back the calendar with the original table
capping start_interval at your start_date value
aggregating values for each interval
You can have three variables to be set, to customize your date intervals and position:
SET #start_date = DATE('2021-10-25');
SET #end_date = DATE('2021-12-04');
SET #interval_days = 7;
Then use the following query, as already described:
WITH RECURSIVE cte AS (
SELECT #end_date AS end_interval,
DATE_SUB(#end_date, INTERVAL #interval_days DAY) AS start_interval
UNION ALL
SELECT start_interval AS end_interval,
GREATEST(DATE(#start_date), DATE_SUB(start_interval, INTERVAL #interval_days DAY)) AS start_interval
FROM cte
WHERE start_interval > #start_date
)
SELECT end_interval, start_interval, SUM(_value) AS total
FROM cte
LEFT JOIN tab
ON tab.created_at BETWEEN start_interval AND end_interval
GROUP BY end_interval, start_interval
Check the demo here.

Calculate year difference between 2 dates with 0 year as 1 year

I have 2 dates to compare so I can count years between both date. If days is less than 365 days then I use interval to make it as 1 year. However I have problem if both date is similar in day for example 2019-10-15 to 2020-10-15 will be displayed as 2 years when I want it to be displayed as 1 year. Here is my code with not the result I want:
SELECT
TIMESTAMPDIFF(
YEAR,
'2019-10-15',
'2020-10-15' + INTERVAL 1 YEAR
) AS `year`
FROM
dob
Result:
What I want is:
2019-10-15 to 2020-10-14 = 1 year
2019-10-15 to 2020-10-15 = 1 year
2019-10-15 to 2020-10-16 = 2 year
How can I achieved that? Thanks in advance.
Does this do what you want? It seems you're only one day out from the expected output so I just subtracted a day.
SELECT
TIMESTAMPDIFF
( YEAR, '2019-10-15',
'2020-10-15'
+ INTERVAL 1 YEAR
- INTERVAL 1 DAY )
AS `year`
FROM dob

How to get data of every first day of month for all month in my sql?

I have a table samples. It has data of every day of every month
date m1 m2 m3
'2017-01-01' 10 11 12
'2017-01-02' 10 10 12
'2017-01-03' 10 11 12
'2017-01-04' 10 8 12
'2017-02-01' 10 6 12
'2017-02-02' 10 14 12
I want the data like this
date m1 m2 m3
'2017-01-01' 10 11 12
'2017-02-01' 10 6 12
You can use following querys
select * from your_table_name
where `date`= DATE_FORMAT(`date` ,'2017-%m-01')
or
select * from your_table_name
where DAY(`date`)= '01' and YEAR(`date`)='2017'
Note that this will return records of every first day of months for the year 2017
SELECT * from `Table` WHERE date_format(date,"%d") = '01'

Query to find the records creating in last 30 mins and then the records created in last 1 hour

I have a db of items from which I need to find the ones that were created in the last 30 mins, and want to order them by their category, then I want items that were created in the last 1 hour but I want to exclude the items found before, and again I want to order them by their category.
The current method I am using is using a union. I am not very sure if this is the best way. Something in my gut tells me there is a better way to do this, just don't know how.
Here's an example set of data and the query
id category_id created_at
1 1 10 mins ago
2 1 12 mins ago
3 2 10 mins ago
4 2 14 mins ago
5 1 40 mins ago
6 2 43 mins ago
7 1 34 mins ago
(select * from items where created_at >= NOW() - 30 mins order by category_id) union (select * from items where created_at >= NOW() - 60 mins and created_at < NOW() - 30 mins order by category_id)
The sample query is not syntactically correct obviously.
Create table
create table items (id int(11), category_id int(11), created_at datetime);
Output:
id category_id created_at
1 1 10 mins ago
2 1 12 mins ago
3 2 10 mins ago
4 2 14 mins ago
5 1 40 mins ago
7 1 43 mins ago
6 2 34 mins ago
Your idea is correct, but the proper syntax is this:
SELECT "last 30 minutes" as t, category_id, count(*) as cnt
FROM items
WHERE created_at >= NOW() - INTERVAL 30 MINUTE
GROUP BY category_id
UNION ALL
SELECT "last 1 hour" as t, category_id, count(*) as cnt
FROM items
WHERE
created_at < NOW() - INTERVAL 30 MINUTE
AND created_at >= NOW() - INTERVAL 60 MINUTE
GROUP BY category_id
...etc...
This query will count the events in the last 30 minutes, grouped by category_id, and then all events in the last hour but not in the last 30 minutes.
UNION ALL
is better than UNION on this context because UNION will return unique rows.
Edit
Based on your updated question, I think you are looking for this:
SELECT items.*
FROM items
WHERE created_at>=NOW() - INTERVAL 60 MINUTE
ORDER BY
(created_at >= NOW() - INTERVAL 30 MINUTE) DESC,
category_id
if you have more intervals then you can use this:
SELECT items.*
FROM items
WHERE created_at>=NOW() - INTERVAL 120 MINUTE
ORDER BY
(created_at >= NOW() - INTERVAL 30 MINUTE) DESC,
(created_at >= NOW() - INTERVAL 60 MINUTE) DESC,
category_id

MySQL Query to select last record for each of the past 7 days

I'm trying to come up with a MySQL query to select the last record from each of the previous 7 days. If 1 of the previous 7 days is missing data, I would only get back 6 records. Here's what I have:
SELECT tracking.* FROM tracking
INNER JOIN
(SELECT MAX(lastChecked) AS maxLastChecked, id FROM tracking
WHERE lastChecked >= DATE_SUB(lastChecked, INTERVAL 7 DAY )
GROUP BY DAY(lastChecked)) as Lookup ON Lookup.id = tracking.id
WHERE tracking.propertyID = 1 ORDER BY tracking.lastChecked ASC LIMIT 7
Basically what this should do is select the final recorded entry for propertyID = 1 in the tracking table for each of the past 7 days (starting on today). However, this query is returning this to me (more than ONLY records within the last 7 days):
ID propertyID lastChecked value
2 1 2012-01-25 05:30:00 280
1 1 2012-01-26 12:34:02 268
5 1 2012-01-27 09:51:31 268
83 1 2012-02-13 00:01:07 276
Any help to fix this up would be greatly appreciated!
Try this query:
SELECT tracking.* FROM tracking
INNER JOIN
(SELECT MAX(lastChecked) AS maxLastChecked, id FROM tracking
WHERE DATEDIFF(lastChecked,NOW())<=7
GROUP BY DAY(lastChecked)) as Lookup ON Lookup.id = tracking.id
WHERE tracking.propertyID = 1 ORDER BY tracking.lastChecked ASC
I believe you should have a system date instead of "lastChecked" in this part:
DATE_SUB(lastChecked, INTERVAL 7 DAY )
Should be:
DATE_SUB(SYSDATE(), INTERVAL 7 DAY )
WHERE lastChecked >= DATE_SUB(lastChecked, INTERVAL 7 DAY )
This condition of your code is going to be true for every record as lastChecked is always greater than lastChecked -7.
So, if you need data of last 7 days replace it with
WHERE lastChecked >= DATE_SUB(SYSDATE(), INTERVAL 7 DAY )