Alter date into text based on month - mysql

I am trying to take a date from one column and convert it to a string into a new column. The capitalization would depend on if the month is June or July. (These are the only two months shown) I tried using the date_format() function but wasn't able to have much success with it.
invoice_date | month_due
2014-07-20 | Due in July 2014
2014-06-30 | DUE IN JUNE 2014

Based on your very little information you are giving, I would suggest the following SQL statement:
SELECT
invoice_date,
CASE MONTH(invoice_date)
WHEN 6 THEN CONCAT("DUE IN JUNE ", CONVERT(YEAR(invoice_date), char))
WHEN 7 THEN CONCAT("Due in July ", CONVERT(YEAR(invoice_date), char))
ELSE "SOME OTHER MONTH"
END month_due
FROM invoice
Here, I suppose the table name is invoice. In any case the month is anything other than 6 or 7 it will display "SOME OTHER MONTH".

Related

How to compare date if one column has start and end date

The column has a start and end date
month_name
23 March, 2018 - 23 April, 2018
23 March, 2018 is the start date and 23 April, 2018 is the end date
How can I use them as to the start date and end date to query?
You would need to use SUBSTRING_INDEX to return a part of the string to the left or right of the hyphen. But this would be terrible in terms of performance. So you need to look at your data structure and redesign accordingly. The start and end dates should be in distinct columns with an INDEX and appropriate DATATYPE set (DATETIME, TIMESTAMP, DATE).
I would suggest that you process the text prior to saving to the database, by using client language regex or split/substring functionality to correctly format the dates into MYSQL format before saving.
set #fromto='23 March, 2018 - 23 April, 2018';
select
str_to_date(left(#fromto,locate('-',#fromto)-1),'%d %M,%Y') datefrom,
str_to_date(right(#fromto,length(#fromto)-locate('-',#fromto)),'%d %M,%Y') dateto;
output:
+------------+------------+
| datefrom | dateto |
+------------+------------+
| 2018-03-23 | 2018-04-23 |
+------------+------------+
short explanation:
set #fromto - defines a variable, which is used as input for this example
locate('-',#fromto) - this will find the length of the part in #fromto before the '-', the -1 is needed because where only want the part before the '-'
length(#fromto)-locate('-',#fromto) - this will find the length of the part in #fromto after the '-'
str_to_date(...) - see STR_TO_DATE
For each and every query that would need to use these dates, you would have to unpick one or both of these dates that are relevant to the query using this kind of text and date manipulation
SELECT .....
WHERE whatever_else
AND STR_TO_DATE(SUBSTRING_INDEX(monthname, ' -', 1 ), '%d %M,%Y') = '2018-03-23'
AND STR_TO_DATE(SUBSTRING(monthname, INSTR(monthname, '- ') +2 ), '%d %M,%Y') = '2018-04-23'
In short your queries would be a complete nightmare to write and maintain and any indexing benefits you might have been able to use had these 2 dates been saved in 2 seperate columns are completely lost.
SUBSTRING_INDEX()
SUBSTRING()
INSTR()
STR_TO_DATE()

How to split this String using mysql Query?

I have a table called "article"
ID Date
1 3rd June 2017
2 2nd April 2016
3 21st June 2017
4 31st December 2015
and I want to find all the ID's where Date has June in it ,Therefore Result should be
ID
1
3
P.S -I tried doing this but I am stuck at this point , here is my Query
SELECT SUBSTRING_INDEX(SUBSTRING_INDEX(Date, ' ', 2), ' ', -1) as month
from article
where article.month='June'
Why would you split the string to do that?
Just do:
where date like '%June%'
You can use date functions in MySQL if you intend to make any more elaborate date comparisons later on:
select id from article where MONTH(STR_TO_DATE(Date,'%D %M %Y'))=6
where 6 corresponds to the 6th month (june).

MYSQL: Inserting time period OR time/moment

I want to build a little calendar system for my website.
When the user creates an appointment he can choose between a time period (like 3rd march to 7th march) and a concrete day with time/moment (like 3rd march 2016 11:00).
I want to insert this into the mysql database.
Values for inserting a time period:
date1: 3rd march 2016
date2: 7th march 2016
Values for inserting a concrete day with time:
datetime: 3rd march 2016 11:00
Now the question I stuck on: How should the table look like?
I thought on sth like this (only the columns):
id | appointment | date1 | date2 | datetime1
And when the user inserts a time period the datetime-field would be empty. But is this the way to go?
One way would be
id
appointment
startdate
starttime (empty if it is an entry for a whole day)
enddate (empty if it is a single entry without a period)
endtime (empty if it is an entry for a whole day)

Mysql SQL for "replace everything but this" where xxx

I've got a terrible database on a project and they've used a text field for dates.
So, I need to build a view that has only the year in one column. The problem is that I have dates with any standard format like:
01-01-2012
01.01.2012
01 01 2012
1/1/2012
01/2012
1/2012
2012
01.2012
Is there any way to build an SQL (MySQL) to get only those 4 year digits to build a view?
Thanks a lot for your help!
It really depends on the whole data structure, you can use REGEX or String functions.
For example, with your sample data the last 4 digits on the right are the year so using
SELECT RIGHT(fieldname, 4) FROM table
would work. If that pattern doesn't work then you've either got to use concat and start splitting them or write a REGEX statement.
If RIGHT will work then you can do an INSERT SELECT
INSERT INTO table (yearcolumn)
SELECT RIGHT(fieldname, 4) FROM table
You can use REGEXP matching, to get rows from given year. There's no way to get a capture from regular expression though.
However, if the year part is alwayst last 4 digits, use RIGHT(). Otherwise, you will need to do reformatting client-side.
This may also help. This is Oracle query for the whole current year. It can be easily converted to any SQL. It uses recursive query to build annual table. Replace SYSDATE and Oracle formats with your version of SQL formats and system date:
WITH data(r, start_date) AS
(
SELECT 1 r, TRUNC(SYSDATE, 'YEAR') start_date FROM dual -- start_date: 1/1/2013
UNION ALL
SELECT r+1, TRUNC(SYSDATE, 'YEAR')+r-1 FROM data WHERE r < 365 -- any number: end_date - start_date or get the number of days in your year your way...
)
SELECT start_date
, TO_CHAR(start_date, 'YYYY') curr_year
, TRUNC(start_date, 'IW') wk_starts
, TRUNC(start_date, 'IW') + 7 - 1/86400 wk_ends
, TO_NUMBER (TO_CHAR (start_date, 'IW')) ISO_wk#
FROM data
/
START_DATE CURR_YEAR WK_STARTS WK_ENDS ISO_WK#
-----------------------------------------------------------------------
1/1/2013 2013 12/31/2012 1/6/2013 11:59:59 PM 1
1/1/2013 2013 12/31/2012 1/6/2013 11:59:59 PM 1
...
12/28/2013 2013 12/23/2013 12/29/2013 11:59:59 PM 52
12/29/2013 2013 12/23/2013 12/29/2013 11:59:59 PM 52
12/30/2013 2013 12/30/2013 1/5/2014 11:59:59 PM 1

Cumulative monthly reporting

I have a MySQL table of photovoltaic electricity generation data (pvdata) from which I need to produce a monthly summary table. A simplified table is shown:
id date time pvdata
1 2012-01-01 10:00 50
1 2012-01-31 12:00 60
1 2012-02-10 13:00 70
2 2012-02-08 10:00 12
2 2012-03-20 10:00 17
The monthly summary table needs to show the cumulative generation for all systems in the database, regardless of whether I have received data for that month, so for example month 3 below contains the total generation from id = 1 (data received in month 2).
Also there may be more than one data point for an id in the same month, so the report must report the max(data) for the month.
year month cum_data
2012 1 60
2012 2 82
2012 3 87
I am pretty new to this, so have struggled for a while. The best I can come up with shows the cumulative total for the month, but without including the cumulative total for ids for which there is no data in the current month:
CREATE TEMPORARY TABLE intermed_gen_report
SELECT year(date) AS year, month(date) AS month, id, max(pvdata) AS maxpvdata
FROM pvdata
GROUP BY id, year(date), month(date)
ORDER BY year(date), month(date);
SELECT year, month, SUM(maxpvdata) AS cum_data
FROM intermed_gen_report
GROUP BY year, month
ORDER BY year, month;
Giving:
year month cum_data
2012 1 60
2012 2 82
2012 3 17
I think the problem is one kind of like this http://www.richnetapps.com/using-mysql-generate-daily-sales-reports-filled-gaps/ - you will want to create a table (possibly temporary) with dates (or year / month values). However that example leaves zeros where there is no data - I think you will want to do a join on a subselect that returns the most recent data before that date (or year/ month value).
I agree I think with what Aerik suggests. You will want to join your data of what is usually called a 'date dimension table'. You can find lots of examples on how to populate said table. This is a common technique in data warehousing.
You can also do what you need in one select using sub selects. Take a look at some of the previous threads like: generate days from date range