First date of any month in SQL - mysql

I am seeking to find first date of the month in the corresponding table:
So if i have 26/08/2011 August as date and 2 months to add, it becomes 26/10/2011. I need the first date of the resulting month- like 01/10/2011.
Can this be achieved in SQL?
Update : I could get the date of the month using
DATEADD(month,months_add, date)
Couldnt get to "beginning of month". Tried: How can I select the first day of a month in SQL?
But for me it throws the error: function pg_catalog.date_diff("unknown", integer, date) does not exist;

You could try using date_add for add two months and date_sub for sub the days -1
set #my_date = "2017-06-15";
SELECT DATE_SUB( DATE_ADD(#my_date, INTERVAL 2 MONTH),
INTERVAL DAYOFMONTH(#my_date)-1 DAY);

SELECT table.date,
table.month_add,
DATE_FORMAT(table.date + INTERVAL table.month_add MONTH,
'%Y-%m-01') AS beginning_of_month
FROM table

Assuming your date is currently a varchar in dd/MM/yyyy format, you can use STR_TO_DATE to convert it to a DATE type column, then use DATE_ADD with your months_add column to dynamically add months then finally use DATE_FORMAT to display it back in a 01/MM/yyyy format with the first day of the month.
SELECT
Date_Column,
Date_Months_Add,
DATE_FORMAT(DATE_ADD(STR_TO_DATE(Date_Column, "%d/%m/%Y" ), INTERVAL Date_Months_Add MONTH), '01/%m/%Y') AS Date_Beginning
FROM sample
Result:
| Date_Column | Date_Months_Add | Date_Beginning |
|-------------|-----------------|-----------------|
| 26/08/2011 | 2 | 01/10/2011 |
| 25/04/2011 | 1 | 01/05/2011 |
| 16/09/2022 | 3 | 01/12/2022 |
| 14/07/2022 | 4 | 01/11/2022 |
Fiddle here.

Related

MySQL MAX foreach day

I have the following table with measured values:
datetime | water | air | conductivity | ...
2021-07-17 16:44:39 | 13,9 | 18,6 | 357 | ...
I am currently querying the values ​​for a period of time:
SELECT * FROM kn1 WHERE datetime > TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 month)) ORDER BY datetime
Now I don't want to get every value, just the highest value of each day.
In general, I can query the highest value through
SELECT MAX(water) FROM kn1 WHERE datetime > TIMESTAMP(DATE_SUB(NOW(), INTERVAL 1 month)) ORDER BY datetime
But this way I get the highest value for the entire period. But I would like to get the highest value for each day in the period.
How can I do this?
Thanks in advance
Use GROUP BY:
SELECT DATE(datetime), MAX(water)
FROM kn1
WHERE datetime > CURDATE() - INTERVAL 1 month)
GROUP BY DATE(datetime);
Note that I modified the WHERE clause to simplify it. Presumably, you don't date about the current time, just the date, so this uses the current date. Second, there is no need for TIMESTAMP, and third, I find interval arithmetic to be simpler without additional functions.

How to showing date on mysql 5.7 from first date of month until end date of month on MYSQL 5.7? [duplicate]

This question already has answers here:
Get a list of dates between two dates
(23 answers)
Closed 1 year ago.
i want to ask how to showing the date from first date of the month until end of date of the month
for example i want to showing date from 2021-01-01 until 2021-01-30. i want join this data with my other table.
iam using MYSQL V5.7
i want this result ::
| 2019-01-01 |
| 2019-01-02 |
| 2019-01-03 |
| 2019-01-04 |
| 2019-01-05 |
| .......... |
| .......... |
| 2019-01-31 |
i try using this Query but doesn't work
SELECT DATE(DATE_SUB(CURRENT_DATE, INTERVAL DAYOFMONTH(CURRENT_DATE)-1 DAY) BETWEEN DATE(NOW()))
Thanks for the answer
If your question is how to return all dates for a single month, you can use a recursive CTE:
with recursive dates as (
select date('2021-01-01') as dte
union all
select dte + interval 1 day
from dates
where dte < last_day(dte)
)
select *
from dates;
This can easily be extended to other date ranges by changing the where condition.
Here is a db<>fiddle.
Old versions of MySQL cannot generate rows that are not stored in a table. I always find myself building a "dates" table to get this done.
You can use this process:
DELIMITER $$
CREATE PROCEDURE fill_dates_table(start_date DATE, end_date DATE)
BEGIN
DECLARE d DATE;
CREATE TABLE IF NOT EXISTS dates (
date DATE NOT NULL PRIMARY KEY
);
SET d = start_date;
WHILE d <= end_date DO
INSERT IGNORE INTO dates VALUES (d);
SET d = d + INTERVAL 1 DAY;
END WHILE;
END $$
DELIMITER ;
Execute this procedure:
CALL fill_dates_table('2019-01-01', '2019-01-31');
Then, use the dates table as you see fit.
If you're using version 8, consider Gordon's answer.

Dynamic due dates checking with the given period of dates

id start_date interval period
1 1/22/2018 2 month
2 2/25/2018 3 week
3 11/24/2017 3 day
4 7/22/2017 1 year
5 2/25/2018 2 week
the above is my table data sample. start_dates will be expired based on interval and period(i.e id-1 will have due date after 2 months from the start_date, id-2 will have due after 3 weeks vice versa). period is enum of (day,week,month,year). Client can give any period of dates. let's say 25-06-2026 to 13-07-2026 like that.. I have to return the ids whose due dates falls under that period.I hope i made my question clear.
Here what i have done to resolve this. I am using mysql 5.7. I found ways to achieve this with recursive CTE's.(not available in mysql 5.7). and there is a way to achieve this by populating virtual records by using inline sub queries along with unions and its a performance killer and there is restriction of population of records.(like given in the link Generating a series of dates) I have reached a point to get results for a single date which is very easy. Below is my query(in oracle)
select id
from (select a.*,
case
when period='week'
then mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),7*interval)
when period='month' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd')=to_char(start_date,'dd')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date),interval)=0
then 0
when period='year' and to_char(to_date('22-07-2018','dd-mm-yyyy'),'dd-mm')=to_char(start_date,'dd-mm')
and mod(months_between(to_date('22-07-2018','dd-mm-yyyy'),start_date)/12,interval)=0
then 0
when period='day'
and mod((to_date('22-07-2018','dd-mm-yyyy')-start_date),interval)=0
then 0 else 1 end filter from kml_subs a)
where filter=0;
But I need to do this for a period of dates not a single date. Any suggestions or solutions will be much appreciated.
Thanks,
Kannan
Assuming this is an Oracle question and not MySQL:
I think the first thing that you need to do is calculate when the due date is. I think a simple case statement can handle that for you:
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
end due_date
Then, using that new due_date field, you can check if the due date falls between the desired date range.
select *
from(
select id,
start_date,
interval,
period,
case when period = 'day' then start_date + numtodsinterval(interval,period)
when period = 'week' then start_date + numtodsinterval(interval*7,'day')
when period = 'month' then add_months(start_date,interval)
when period = 'year' then add_months(start_date,interval*12)
else null end due_date
from data)
where due_date between date '2018-02-25' and date '2018-03-12'
The above query checking between 2/25/18 and 3/12/18 produces the following output using your data:
+----+-------------+----------+--------+-------------+
| id | start_date | interval | period | due_date |
+----+-------------+----------+--------+-------------+
| 2 | 05-FEB-2018 | 3 | week | 26-FEB-2018 |
| 5 | 25-FEB-2018 | 2 | week | 11-MAR-2018 |
+----+-------------+----------+--------+-------------+

Generate Monthly XML from a table containing date range

I have a table as -
test_table(booking_id, booking_description, start_date, end_date)
Sample Data -
1 | Some booking | 06/30/2013 | 08/01/2013
2 | Some new one | 08/05/2013 | 09/01/2013
3 | Some new two | 09/03/2013 | 09/05/2013
Now I want to generate a monthly xml file from using some java code (No problem in it, I would write), I would be passing the month and year (basically start and end date of the month) to mysql query and I want some table as -
month = 7, year 2013
1 | Some booking | 07/01/2013
1 | Some booking | 07/02/2013
...
Month = 9, year = 2013
2 | Some new one | 09/01/2013
| | 09/02/2013
3 | Some new two | 09/03/2013
...
I was looking to use a java loop from start date to end date and query mysql to find out whether this date comes in the date range or not, if it comes I would add the details else I would add blanks. But that is going to be horrible approach (will go for 30 times mysql look ups) and I am considering it as last option.
Is there any other way around with one or two mysql query and get the data in the format.
EDIT:
month = 7, year = 2013
Select *
from booking_details
where month(start_date) <= 7 and year(start_date) <= 2013 and
month(end_date) >= 7 and year(end_date) >= 2013
I developed this query but still not sure would it over all the possible scenarios.
Based on my understanding of the question you want something like this:
declare #date datetime
Select booking_id, booking_description, start_date --you don't indicate which date field you want in the results
from test_table
where (start_date between #date and date_add(#date, INTERVAL 1 MONTH))
or (end_date between #date and date_add(#date, INTERVAL 1 MONTH))
SQL is probably not exact, I know TSQL not MySQL but this should be close.

How to use a string/column value as a mysql date interval constant (DAY, MONTH...)?

I have three columns: a date column, a integer column, and a varchar column like this:
+------------+------+---------+
| date |value | unit |
+------------+------+---------+
| 2009-01-01 | 2 | DAY |
| 2009-02-01 | 3 | MONTH |
+------------+------+---------+
I want to use the values of the integer and the varchar column in a mysql date_add() function as part of the "INTVERAL" expression, added to the date in the 'date' column.
For example:
date_add(2009-01-01, INTERVAL 2 DAY), so that the '2009-01-01' is from the 'date' column, the '2' is from the "value"/integer column and the "DAY" is from the 'unit'/varchar column.
And the select would look like this:
select date_add(table.date_column, INTERVAL table.integer_column table.varchar_column) from table
Problem is: it doesn't work. The date and the integer column work, so this is ok:
select date_add(table.date_column, INTERVAL table.integer_column DAY) from table
but as soon I try to replace the "DAY" Keyword with a string value from a column I get an error message.
Any Ideas?
I guess more generally the problem is:
How do I use dynamically retrieved values as constants/key expressions? Is there a kind of "eval" function in mysql ?
This problem has been bugging me for a long time now, any help would be really great.
Beat
Unfortunately MySQL expects a keyword after INTERVAL and not any string or numeric value. You can achieve what you want by using a CASE statement and give the different cases with the different keywords.
As an example, let's say you want to add the value with the appropriate unit to the date then the SQL statement would be as follows:
SELECT CASE unit
WHEN "DAY" THEN date_add(date, INTERVAL value DAY)
WHEN "MONTH" THEN date_add(date, INTERVAL value MONTH)
END
AS newDate
FROM table
Also works in the WHERE clause by the way :)
I think you're better off using a CASE statement for each possible value of the unit column, since it is a finite universe. You can choose whether to keep the column as a varchar, or use an integer code instead.
I would discourage use of dynamically executing SQL statements, even when generated from an existing table unless you are 120% careful in restricting the values that get inserted in the table. What would you do if you somehow got the following values in the table? Oops!
+------------+------+------------------------------------+
| date |value | unit |
+------------+------+------------------------------------+
| 2009-01-01 | 2 | DAY |
| 2009-02-01 | 3 | MONTH |
| 2009-03-01 | 4 | DAY) FROM table; DROP TABLE table; |
+------------+------+------------------------------------+
I'm in the middle of reinstalling MySQL on my machine, so I can't test it, but perhaps concatenating them into a valid string might help, if CONCAT() is allowed here:
SELECT
DATE_ADD(
table.date_column,
INTERVAL CONCAT(
table.integer_column,
' ',
table.varchar_column
)
)