I am trying to query a timesheet where time span (cycle) is 21 to 20, thus today (10/30/2014) is November.
So, 10/14/2014 is October.
2014-09-21 and 2014-10-20 is one time span
2014-10-21 and 2014-11-20 is one time span
The table is simply storing the date for the timesheet:
id date hours
So, I can specifically say:
SELECT * FROM rapoarte WHERE DATE(ziua) BETWEEN "2014-09-21" AND "2014-10-20"
But I can't figure out how to:
How can I query through this interval for say 1 year (or more)
How can I query for this month?
dynamically
The easiest way is to do date arithmetic. So, for October, you would use:
SELECT *
FROM rapoarte
WHERE month(DATE(ziua) - interval 20 day + interval 1 month) = 10
The idea is to subtract 20 days and add a month. This seems to be the logic for the reporting month.
You can add this as a field:
SELECT *,
date_format(month(DATE(ziua) - interval 20 day + interval 1 month), '%Y-%m') as ReportingMonth
FROM rapoarte
WHERE month(DATE(ziua) - interval 20 day + interval 1 month) = 10
EDIT:
If you want data for this reporting month:
WHERE month(DATE(ziua) - interval 20 day + interval 1 month) = month(DATE(now()) - interval 20 day + interval 1 month) and
year(DATE(ziua) - interval 20 day + interval 1 month) = year(DATE(now()) - interval 20 day + interval 1 month)
Related
I'm working with MySQL, and attempting a specific time range query. For example if it's august now, I'm attempting to query from September 1st at midnight, to August 1st at midnight.
So far I'm able to get my date range successfully selected thanks to a prior question, but the problems I'm having are:
-My database columns for time are in UTC, and I need to convert to my timezone
-I'm having trouble adding the specific time into my query.
Here is my current query:
select column1,date_time_column from table.x
where date_time_column > concat(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day
and date_time_column < concat(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
order by date_time_column
;
I'm attempting to put my specific time as 05:00:00, which is midnight in my DB, but right now when I run my select, it's still showing 00:00:00 times, which makes me think my time isn't applying or I have my syntax for adding the time incorrect. Any help would be much appreciated.
Use DATE_FORMAT instead of CONCAT
SELECT
DATE_FORMAT(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day,
DATE_FORMAT(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
DATE_FORMAT(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day | DATE_FORMAT(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
:---------------------------------------------------------------------------------------- | :----------------------------------------------------------------------------------------
2021-07-01 05:00:00 | 2021-08-01 05:00:00
db<>fiddle here
select column1,date_time_column from table.x
where date_time_column > DATE_FORMAT(last_day(curdate() - interval 2 month), '%Y-%m-%d 05:00:00') + interval 1 day
and date_time_column < DATE_FORMAT(last_day(curdate() - interval 1 month), '%Y-%m-%d 05:00:00') + interval 1 day
order by date_time_column
;
How to select all data from last month (or 30 days)?
I already found some answers, and mostly gives this solution
SELECT *
FROM gigs
WHERE date > DATE_SUB(CURDATE(), INTERVAL 3 MONTH)
ORDER BY date DESC
But this gives me also the dates from the future
I am only interested in the days from last month or 30 days (not next month and beyond)
Is this what you want?
WHERE date > DATE_SUB(CURDATE(), INTERVAL 1 MONTH) AND date <= CURRENT_DATE
I added a condition so the query filters on date not greater than today. I also modified your code so the date range starts one month ago (you had 3 months).
try this code
SELECT * FROM gigs
WHERE date BETWEEN CURDATE() - INTERVAL 30 DAY AND CURDATE()
ORDER BY date DESC
You are asking for two separate things.
The last 30 days is easy.
date between now() - interval 30 day and now()
Data this month is like this:
date between (last_day(Now() - INTERVAL 1 MONTH) + INTERVAL 1 DAY) and last_day(Now())
Data a few months ago is like this:
date between (last_day(Now() - INTERVAL 4 MONTH) + INTERVAL 1 DAY)
and
(last_day(Now() - INTERVAL 3 MONTH) + INTERVAL 1 DAY)
I am trying to get records from last one year and upto last date of provious month i.e. not including the current month. Here's my query:
SELECT `customer_id`, `customer_name`, `customer_date`
FROM `customers`
WHERE DATE(`customer_date`) <= (CURDATE() - INTERVAL 1 MONTH)
AND DATE(customer_date) >= (CURDATE() - INTERVAL 12 MONTH)
This query fetches records from 1 May, 2018 to 8 April 2019.
INTERVAL 1 MONTH fetches records 30 days ago. What I need to do something here?
I want to exclude current month records, so query should return records upto 30 April 2019. How do we do that?
You must correctly calculate the first and last days of range with help LAST_DAY() function. For example:
Calculate the first day of the range
SELECT LAST_DAY(CURDATE() - INTERVAL 13 MONTH) + INTERVAL 1 DAY
Output:
2018-05-01
Calculate last day of the range
SELECT LAST_DAY(CURDATE() - INTERVAL 1 MONTH)
Output:
2019-04-30
The full query might look like:
SELECT `customer_id`, `customer_name`, `customer_date`
FROM `customers`
WHERE `customer_date` >= LAST_DAY(CURDATE() - INTERVAL 13 MONTH) + INTERVAL 1 DAY
AND `customer_date` <= SELECT LAST_DAY(CURDATE() - INTERVAL 1 MONTH)
To get data up to the previous month:
where customer_date < curdate() + interval (1 - day(curdate()) day
Why? First note that there is no function call on the customer_date. So, this expression is index-compatible and can use an index.
Second, this structure works both for dates and date/times. That is very handy, because it may not always be obvious if a column has a time component (people are not very good about naming columns to capture this information).
You claim that the "12 months" ago portion works. That doesn't look correct to me. For the complete logic:
where customer_date < curdate() + interval (1 - day(curdate()) day and
customer_date >= (curdate() + interval (1 - day(curdate()) day) - interval 1 year)
SELECT `customer_id`, `customer_name`, `customer_date` FROM `customers` WHERE
MONTH(`customer_date`) <= (CURDATE() - INTERVAL 1 MONTH) AND
MONTH(customer_date) >= (CURDATE() - INTERVAL 12 MONTH)
hope this help
I'm doing a review of existing code and have found the following SQL query which is used to get a selection of records last month.
Is there a more concise way of writing SQL to do what this date based clause does in MySQL?
SELECT foo
FROM some_table
WHERE some_date
BETWEEN
DATE_FORMAT(LAST_DAY((NOW() - INTERVAL 1 MONTH) - INTERVAL 1 SECOND), '%Y-%m-01 00:00:00')
AND
DATE_FORMAT(LAST_DAY((NOW() - INTERVAL 1 MONTH) - INTERVAL 1 SECOND), '%Y-%m-%d 23:59:59')
It works, but I just twitch a little every time I see it.
Can anyone else write it better?
Thank you in advance.
There's no need to format the dates, they default to YYYY-MM-DD 00:00:00.
This is a little bit simpler:
SELECT foo
FROM some_table
WHERE some_date >= LAST_DAY(CURDATE() - INTERVAL 2 MONTH) + INTERVAL 1 DAY
AND some_date < LAST_DAY(CURDATE() - INTERVAL 1 MONTH) + INTERVAL 1 DAY
So if CURDATE() is today, 2019-02-06, then:
- INTERVAL 2 MONTH is 2018-12-06
LAST_DAY() of that date is 2018-12-31
+ INTERVAL 1 DAY is 2019-01-01
Then the upper bound is:
- INTERVAL 1 MONTH is 2019-1-06
LAST_DAY() of that date is 2019-1-31
+ INTERVAL 1 DAY is 2019-02-01
The dates should be strictly less than 2019-02-01.
Using less than accounts for timestamps in the last second of the month, between 23:59:59.000 and 23:59:59.999.
In MySQL, I can do something like:
SELECT DATE_ADD('2010-07-02', INTERVAL 1 MONTH)
And that returns:
2010-08-02
That's great... now is there a MySQL function that I can use to find what the date would be one month in advance on the same day. For example, 7/2/2010 falls on the first Friday of July, 2010. Is there an easy way to find what the first Friday of August, 2010 is with an SQL statement?
It got a bit complicated, but here goes:
SELECT IF(MONTH(DATE_ADD('2010-07-02', INTERVAL 28 DAY)) = MONTH('2010-07-02'),
DATE_ADD('2010-07-02', INTERVAL 35 DAY),
DATE_ADD('2010-07-02', INTERVAL 28 DAY));
Rationale: If you add 4 weeks or 5 weeks, you're still on the same day; since all months are between 28 and 35 days long, if 4 weeks later is still the same month, add another week.
UPDATE: Umm, I did not think this through very well - it works for first X in month, but necessarily for 2nd, 3rd... (i.e. 3rd X in month might return a 2nd X next month). Try #2:
SELECT IF(
CEIL(DAY(DATE_ADD('2010-07-02', INTERVAL 35 DAY)) / 7) = CEIL(DAY('2010-07-02') / 7),
DATE_ADD('2010-07-02', INTERVAL 35 DAY),
DATE_ADD('2010-07-02', INTERVAL 28 DAY));
Rationale: CEIL(DAY(x) / 7) is x's week number. If it's different when you add 5 weeks, then add 4 weeks.
UPDATE 2: LOL, I suck today, I should really think before I post... Week is usually defined as Mon-Sun, or Sun-Mon, not as from whatever started the month till 6 days later. To compensate for this:
SELECT IF(
CEIL((DAY(DATE_ADD('2010-07-02', INTERVAL 28 DAY)) - DAYOFWEEK('2010-07-02')) / 7)
= CEIL((DAY('2010-07-02') - DAYOFWEEK('2010-07-02')) / 7),
DATE_ADD('2010-07-02', INTERVAL 28 DAY),
DATE_ADD('2010-07-02', INTERVAL 35 DAY));
Does this do the trick?
SELECT DATE_ADD(
DATE_SUB(
DATE_ADD('2010-07-06', INTERVAL 1 MONTH),
INTERVAL DAYOFWEEK(DATE_ADD('2010-07-06', INTERVAL 1 MONTH)) DAY
),
INTERVAL DAYOFWEEK('2010-07-06') DAY
)