SQL query matching minimum X row count within any 30 day range - mysql

Assume table contains the following columns name, created_at which string and date types.
Looking for any help to make a SQL query that outputs rows within any 30-day range where there are at least 5 or more rows that has the created_at column of the table inside that range.
The query can just output the rows or the last one in the range - whichever is easy.
The 30-day range can start from today and go backwards or from the first row forward etc.
created_at can be grouped if required.

I think this is an aggregation query with filtering:
select name, max(created_at)
from t
where created_at >= #start - interval 30 day and
created_at < #start
group by name
having count(*) >= 5;

Related

MYSQL: How to get rows till specific month's end from very start

I'm working on a project for a Fuel Pump. Here is my table for the records:
I want to display rows from very start (2019-07-03) till the end of the specific month (e.g 2019-09-29) . How could i do achieve this?
A simple WHERE clause will do the trick
SELECT id, date, total_amount, total_paid
FROM table
WHERE date <= LAST_DAY(CURDATE())
CURDATE() will return current date i.e. 2019-09-08
LAST_DAY() will return the last date of current month i.e. 2019-09-30
WHERE clause will return all rows with date <= 2019-09-30
Update
If you want to filter records based on user input which is month and year ( 2019-09 ) then either it can done by appending '-01' at scripting side or using CONCAT at MySQL level,
WHERE date <= LAST_DAY(CONCAT('2019-09', '-01'))
I think this will work. You can change dates accordingly.
Select *
From table
Where date>='2019-07-03' AND date<='2019-09-29'

MySQL find date range with count

In MySQL, it is fairly easy to find the number of records that exist within some time interval.
SELECT COUNT(*) FROM records WHERE create_date > '2018-01-01 01:15:00' AND create_date < '2018-01-01 02:15:00'
But I want to do the opposite, sort of. Rather than providing a time interval and getting a count of records, I want to provide a count of records and check if a X minute time interval exists where more than Y many records were created. Getting the exact time interval is not essential, only if one exists or not. At a higher level, I am attempting to identify if there was any X minute "surge" when more than Y records where created during the course of a day.
For example, in the past 24 hours was there any 1 hour interval where a "surge" of more than 50 new records occurred?
I have already ruled out dividing the 24 hours into blocks of 1 hour intervals and checking each block. This does not work because the "surge" could span two sequential 1 hour blocks, such as 25 records at the end of the 01:00:00 block and 25 records at the beginning of the 02:00:00 block.
This should do it:
SELECT COUNT(*)
FROM records r1
WHERE
(SELECT COUNT(*) FROM records r2
WHERE ABS(UNIX_TIMESTAMP(r1.create_date) - UNIX_TIMESTAMP(r2.create_date)) < X) > Y
What this does is count how many records have more than Y records that have been created within X seconds after or before each record.
So basically it will return >=1 if there are any, 0 if not.
So if you wanted to sort by hours you would want to group the records. Here I'm using the built-in functions that return parts of a timestamp, year(), month(), dayofmonth(), hour(). Since you can't use an aggregate function in the where clause I had to use having to limit by the count requirement.
select date(create_date),
hour(create_date),
count(*) as surge from records
where create_date > curdate() - interval 1 day
group by year(create_date), month(create_date),
dayofmonth(create_date), hour(create_date)
having count(*) > 50;
Another method to accomplish your goal might be to select the count of records and group by the interval in question. In this case I'm adding an hour to the create_date to get your 1 hour suggested interval. Anytime the count is greater than 50 it returns a row. Notice I'm also grouping by the hour. This is to prevent multiple starts for a "surge" within the same hour:
select create_date,count(*) as surge from records
group by year(create_date), month(create_date),
dayofmonth(create_date),hour(create_date),
(create_date + interval 1 hour - create_date) having count(*) > 50;
The problem with this however is that some surges may last longer than 1 hour, but it should give you the moment the "surge" started.

Selecting a 30 EOD records from an hourly set in MySQL

I'm a novice mySQL dev and I'm trying to tackle something a little tricky. I have a table full of hourly records that are timestamped on 'created'.
I need to write a query that will pull 30 records from the table where each record is the last record of the day for the 30 days starting from NOW().
I subsequently need to do the same for 24 weeks and 12 months but I assume once I have 1 query ironed out for the days, I can figure out the rest.
Thanks in advance
This isn't hard if you use an appropriate aggregate query.
Assuming your table is records and your DATETIME or TIMESTAMP column is called time_stamp.
Try this:
SELECT DATE(time_stamp) AS the_day,
MAX(time_stamp) AS eod_timestamp
FROM records
WHERE time_stamp >= CURDATE() - INTERVAL 30 DAY
GROUP BY DATE(time_stamp)
This gets the latest (MAX) time_stamp for each day in the table for the last 30 days.
If you want to locate the exact rows in records that have those end-of-day timestamps, you can join this aggregate query to the records table like so.
SELECT eod.the_day, r.whatever, r.whatever, r.whatever
FROM records AS r
JOIN (
SELECT DATE(time_stamp) AS the_day,
MAX(time_stamp) AS eod_timestamp
FROM records
WHERE time_stamp >= CURDATE() - INTERVAL 30 DAY
GROUP BY DATE(time_stamp)
) AS eod ON r.time_stamp = eod.eod_timestamp
Notice that the ON clause in the query pulls out the rows from records that have the end-of-day timestamps. If more than one record has the same end-of-day timestamp, this query will get them all.

Empty result when using mySQL WEEK() to find dates in current week

We are using the following statement to select dates of birth which occur in the current week:
SELECT * FROM tbl_user WHERE WEEK(dob,1) = WEEK(CURDATE(),1) ORDER BY id DESC
Our 'dob' column has the type DATE and contains 1 record where dob is 1972-07-09. However, when we run our query (today is 2014-07-07) we get an empty result.
Any ideas why?? Does WEEK() only work on columns with type DATETIME?
Thanks in advance for an help!
SELECT WEEK('1972-07-09',1); //result= 27
SELECT WEEK('2014-07-07',1); //result=28
For Example :
SELECT WEEK('2014-01-18',1); //result=3
Your where condition does not satisfy that why It's return false and Empty Result.
Check Manual here
2014-07-07 is week 28 and 1972-07-09 is week 27. 27 is not equals 28 so you get no result.
You can check this with that query:
select week('2014-07-07',1),week('1972-07-09',1) from tbl_user ;
SELECT WEEK('1972-07-09',1);
result: 27
SELECT WEEK('2014-07-07',1);
result: 28
In this case your condition WHERE WEEK(dob,1) = WEEK(CURDATE(),1) is False. That's why you get an empty result.
Your definition of week is not the same as MySQLs. For a better and more efficient result you should instead decide on the min and max range you wish to find and select that which allows you to define when your week starts and ends.
SELECT *
FROM tbl_user
-- min range == 00:00:00 on the first day of week
WHERE dob >= ADDDATE(CURRENT_DATE, INTERVAL 1-DAYOFWEEK(CURRENT_DATE) DAY)
-- max range == 00:00:00 on the first day of next week
AND dob < ADDDATE(CURRENT_DATE, INTERVAL 8-DAYOFWEEK(CURRENT_DATE) DAY)
ORDER BY id DESC
The start and end date can be adjusted as needed, but because you aren't applying a function to the dob field you will avoid a table scan.

Calculate difference between dates

The title might be a bit misleading, but what I want is:
SELECT * FROM table ORDER BY pid ASC
And in one of the columns I have a DATE(). I want to compare the current date (not time) and return how many days are left till that date. Let's say the date is 2013-04-20 and today's date is 2013-04-16 I don't want to get any data if it's < current date. If it is I want it returned in days.
I've been looking around here and I've found no way to do it, and I can't for the love of me figure it out.
If you're looking for the difference between two date you can use the GETDATE function in MS SQL
SELECT DATEDIFF(DD, DateOne, DateTwo) FROM TABLE
This will return the difference in number of days between the two dates.
If you only want rows where the date field is less than or equal to today's date you can use:
SELECT DATEDIFF(DD, DateField, GETDATE())
FROM TableName
WHERE DateField <= GETDATE()
If you're using MySQL you can use DATEDIFF()
SELECT
DATEDIFF(NOW(), date_column) AS days_diff
FROM
tablename
Get the difference between two dates (ANSI SQL)
select the_date_column - current_date as days_left
from the_table
where the_date_column - current_date <= 4;
SQLFiddle: http://sqlfiddle.com/#!12/3148d/1