i have the data which look like this
Day Month Time
11 02 12:11:11
12 02 10:10:20
13 02 9:12:6
14 02 6:7:2
as you can see the data in Time Column is not Timestamp but String, therefore some of The Data has the wrong Format like this: 9:12:6 not 09:12:06.
what i want to do now is a new Colum which combine String of Day, Month, and correct Time Format, the ":" need to be removed.
The Result should looks like this:
new Colum
1102121111
1202101020
1302091206
1402060702
Can you please help me?
Thanks
CREATE TABLE Saletime (
day VARCHAR(02) NOT NULL,
month VARCHAR(02) NOT NULL,
time VARCHAR(10) NOT NULL);
INSERT INTO saletime(day, month, time) VALUES ('11','02','12:11:11');
INSERT INTO saletime(day, month, time) VALUES ('12','02','10:10:20');
INSERT INTO saletime(day, month, time) VALUES ('13','02','9:12:6');
INSERT INTO saletime(day, month, time) VALUES ('14','02','6:7:2');
Concatenate the values then parse them
select to_char(
to_timestamp(
day||'-'||month||' '||time,
'DD-MM HH24:MI:SS'),
'DDMMHHMISS')
from Saletime;
SQL Fiddle example
Since the inputs and the output are all strings, perhaps direct string manipulation makes sense. (It would be much better if the output were date data type, but that is in your hands, not in mine.)
I follow your lead in using day and month as column names. That is a very poor practice; I hope your actual column names are different.
It's not clear if you may need the same left-padding with 0 for the day and month; just in case, I handled it too (it's done the same way).
select day, month, time,
lpad(day, 2, '0') || lpad(month, 2, '0')
|| lpad(regexp_substr(time, '\d+', 1, 1), 2, '0')
|| lpad(regexp_substr(time, '\d+', 1, 2), 2, '0')
|| lpad(regexp_substr(time, '\d+', 1, 3), 2, '0') as new_string
from saletime;
DATE MONTH TIME NEW_STRING
---- ----- --------- ----------
11 02 12:11:11 1102121111
12 02 10:10:20 1202101020
13 02 9:12:6 1302091206
14 02 6:7:2 1402060702
You can do this as a numeric calculation:
select (day * 100000000 +
month * 1000000 +
cast(regexp_substr(time, '[0-9]+', 1, 1) as number) * 10000 +
cast(regexp_substr(time, '[0-9]+', 1, 2) as number) * 100 +
cast(regexp_substr(time, '[0-9]+', 1, 3) as number) * 1
)
from saletime;
Here is a SQL Fiddle.
If you want this as a string, just convert it to a string.
Related
I have a list of months formatted with the 3 letter abbreviation followed by the last 2 numbers of the year.
For example, this current month would be SEP22. I need to find a way to turn this from a varchar into a date/datetime value, pointing to the first day of the month.
So, if I have 'SEP22', I need to get the output of September 1st, 2022 as a date/datetime object.
I can find a lot of data on turning the datetime value or numeric month into the abbreviation, but not the other way around.
I know I can make a giant case statement, but I was wondering if there's an easier method to read this type of data.
Any and all help is appreciated.
EDIT: I know the data is in the current century, I know where the data comes from and when it started being collected, all of this data has been collected in or after August 2013 (AUG13).
Try this:
SELECT
CAST(
LEFT(StringDate, 3) -- e.g. SEP
+' 1 20' -- assumes 21st century
+ RIGHT(StringDate, 2) -- e.g. 22
AS DATE
) AS ActualDate
;
For SQL Server:
convert(date, '01 ' + LEFT('SEP22', 3) + ' ' + RIGHT('SEP22', 2), 6)
When SQL Server converts the date from a string with a 2-digit year, the cutoff is at 50:
declare #myMonth table (
mo varchar(5)
)
declare #i int = 0
while #i < 100
begin
set #i = #i + 1
insert #myMonth
values ('SEP' + RIGHT('0' + CAST(#i AS VARCHAR(5)), 2))
end
SELECT mo
, convert(date, '01 ' + LEFT(mo, 3) + ' ' + RIGHT(mo, 2), 6)
FROM #myMonth
For Oracle:
TO_DATE('01' || 'SEP22', 'DDMONYY')
For Oracle, all of the dates are after 2000:
CREATE TABLE MYMONTH (
MO VARCHAR2(6) NOT NULL
)
;
INSERT INTO MYMONTH (MO)
SELECT 'SEP' || SUBSTR('0' || CAST(N AS VARCHAR2(5)), -2)
FROM (
SELECT (0 + ROWNUM) N
FROM DUAL CONNECT BY ROWNUM <= 100
)
;
SELECT MO
, TO_CHAR(TO_DATE('01' || MO, 'DDMONYY'), 'MM/DD/YYYY')
FROM MYMONTH
;
I have 1 column that displays year number in the format 1999 and I have another column that displays month number as 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12.
How do I get the single months to display with a 0 in front? I need to combine these 2 columns to display in the form of yyyy/mm so it will be 1999/01 for January 1999.
I tried:
SELECT
YearNumber + '/' + FORMAT(MonthNumber, 'mm') AS PaymentMonth
But I get this error:
Conversion failed when converting the varchar value '/' to data type smallint
Please try:
SELECT
CAST(YearNumber AS varchar(4)) + '/' +
LEFT('0' + CAST(MonthNumber AS varchar(2)), 2) AS PaymentMonth;
Another option, using case when:
The table:
select * from mytable
# YearNumber MonthNumber
# 1999 2
# 2000 11
select YearNumber || '/' ||
(case when MonthNumber < 10 then '0' else '' end) ||
MonthNumber as YearMonth
from mytable
# YearMonth
# 1999/02
# 2000/11
Note: the above works in sqlite, which tends to be more permissive with column types. In SQL Server, if the columns are not strings already then you may need to cast(YearNumber as char(4)) or perhaps use the concat function:
select
concat(YearNumber, '/',
(case when MonthNumber < 10 then '0' else '' end),
MonthNumber) as YearMonth
from mytable
Other DBMSes have different dialects, they may differ slightly.
SQL Date Format with the FORMAT function
Use the FORMAT function to format the date and time data types from a date column (date, datetime, datetime2, smalldatetime, datetimeoffset, etc. data type) in a table or a variable such as GETDATE()
To get DD/MM/YYYY use SELECT FORMAT (getdate(), 'dd/MM/yyyy ') as date
To get MM-DD-YY use SELECT FORMAT (getdate(), 'MM-dd-yy') as date.
You can use the concat() function to join them. Depending on the database you can use || instead.
select concat(col1, '/', col2) from tbl;
This is also standard, but not enabled by default on MySQL, and possibly other databases.
select col1 || '/' || col2 from tbl;
Long story short, I was handed this query (edited a bit for the forum world) to get it working in order to start creating reports. Having some issues with the 3 CASE statements (tried to add comment within the code to explain a little better what is happening). All data is being pulled from the same table/view.
I know I need to create some nested SELECT statements in order to make it work, but I'm struggling. What I'm trying to have happen is...
CASE 2 to only run if CASE 1 IS NOT NULL, where the column would be a result of (amd_month + 1 month). Format being YYYYMM
CASE 3 to only run if CASE 2 IS NOT NULL, where the column would be a result of (ext_srg_start_date + 6 months). Format being YYYYMM
SELECT
part,
amd_month,
amd actual_demand,
round(roll_12amd * 1.15) srg_lmt,
round(roll_12amd * 1.5) ext_srg_lmt,
-- CASE: 1
-- calculate level- COMPLETE
CASE
WHEN (amd > roll_12amd * 1.5) THEN 'Extreme Surge'
WHEN (amd > roll_12amd * 1.15) THEN 'Surge'
ELSE NULL
END AS srg_nt,
-- CASE: 2
-- if amd_month = 12, (+1 year to) and (-11 from month) from ext_srg_start_date,
-- else +1 month to ext_srg_start_date - COMPLETE
CASE
WHEN substr(amd_month, 5, 2) IN (
'12'
) THEN concat(TO_CHAR(substr(amd_month, 1, 4) + 1), lpad(TO_CHAR(substr(amd_month, 5, 2) - 11), 2, '0'))
ELSE concat(substr(amd_month, 1, 4), lpad(TO_CHAR(substr(amd_month, 5, 2) + 1), 2, '0'))
END AS ext_srg_start_date,
---- CASE: 3
---- +6 to ext_srg_start_date - IN PROGRESS
CASE
WHEN substr(amd_month, 5, 2) IN (
'01',
'02',
'03',
'04',
'05',
'06'
) THEN concat(substr(amd_month, 1, 4), lpad(TO_CHAR(substr(amd_month, 5, 2) + 6), 2, '0'))
ELSE concat(TO_CHAR(substr(amd_month, 1, 4) + 1), lpad(TO_CHAR(substr(amd_month, 5, 2) - 6), 2, '0'))
END AS ext_srg_carry_date
FROM
connect.table
Any help would be awesome. Thanks!
You can do away with case statements 2 and 3 if AMD_Month is a date data type, you can also do away with them if it's not but it takes an extra step:
If AMD_Month is a Date column then ext_srg_start_date and ext_srg_carry_date could be defined as:
...
, AMD_Month + INTERVAL '1' MONTH ext_srg_start_date
, AMD_Month + INTERVAL '6' MONTH ext_srg_carry_date
...
If AMD_Month is a string, then you first need to convert it to a date and I guess then convert the result back to a string:
...
, TO_CHAR( TO_DATE( AMD_Month, 'YYYYMM')
+ INTERVAL '1' MONTH, 'YYYYMM') ext_srg_start_date
, TO_CHAR( TO_DATE( AMD_Month, 'YYYYMM')
+ INTERVAL '6' MONTH, 'YYYYMM') ext_srg_carry_date
...
Date arithmatic works so much better when you store date data types as dates or timestamps than when you store them as strings.
Have a text string that I need to convert to date, however, it's not the generic yyyymmdd string. e.g. March 2018 is stored as '2018m3' as are all other dates. Is there a way to convert the string to a normal date in Oracle?
This may be helpful :
SQL> SELECT to_date('2018m3', 'YYYY"m"MM') FROM dual
2 /
Output
TO_DATE('2018M3','YYYY"M"MM')
-----------------------------
3/1/2018
If that is the format, you can do:
select add_months(to_date(substr(col, 1, 4) || '0101'),
to_number(replace(substr(col, -2), 'm', '')) - 1
)
An alternative method:
select to_date(substr(col, 1, 4) || regexp_substr(col, '[0-9]+', 1, 2), 'YYYYMM')
I need to create a report that returns a range of data, based on an open date and any records opened within a month for each previous quarter.
So if I was to run the report at the start of August - it would show records which have an open date within May, Feb, November, August with no limit on the year. The open date month will be defined by the month where the report is run.
I have this very basic code
SELECT RecordMonth, RecordYear, caseRef, caseDescription,
caseOpenDate, caseClosedDate, PersonName, PersonSurname
FROM dbo.casereview
WHERE month(caseopendate) = 03
OR month(casecopendate) = 06
OR month(caseopendate) = 09
OR month(caseopendate) = 12
Issue is, I need this to run dynamically, so whichever month it is run, it can show cases where the open date falls within the previous quarters/months.
You can use Modulo to calculate the 4 month numbers you need based on the current system date then filter on those.
In you case something like this will work.
DECLARE #month int = month(getdate())
DECLARE #m1 int = ((#month -1 ) % 12) +1
DECLARE #m2 int = ((#month + 2) % 12) +1
DECLARE #m3 int = ((#month + 5) % 12) +1
DECLARE #m4 int = ((#month + 8) % 12) +1
SELECT RecordMonth, RecordYear, caseRef, caseDescription,
caseOpenDate, caseClosedDate, PersonName, PersonSurname
FROM dbo.casereview
WHERE month(caseopendate) IN (#m1, #m2, #m3, #m4)
So first this is to get the current month number, we do this by using getdate() to get the current date and the MONTH function to return just the month number. So today this will equal 8.
Next we use Modulo (the % sign) to work out what months we need.
So for example if month = 6 then #m4 is worked out as
(#month + 8) = 14
14 % 12 = 2 (remainder of 14 divided by 12)
2 + 1 = 3
Note: I've made this a bit longer than it needs to be so it's a bit easier to read. We could put the calcs for #m1, #m2 etc directly into the select statement but doing this separately makes it clearer.
Notice I also used an IN statement rather than a bunch of ORs in the WHERE clause. IN just matches on any of the values listed in the parentheses.
Assuming you want all matching rows in opendate order, we can simply use the Modulus function. We could do four MONTH % 12 queries, or a single MONTH % 3 query.
I built a test database to show the basic process:
create database [_TEST_QUARTERS];
GO
USE [_TEST_QUARTERS];
GO
create table [CASEREVIEW] (
[CASE_ID] integer primary key,
[CASEOPENDATE] date
);
insert into [CASEREVIEW] values ( 1, '2016-09-19');
insert into [CASEREVIEW] values ( 2, '2016-10-20');
insert into [CASEREVIEW] values ( 3, '2016-11-11');
insert into [CASEREVIEW] values ( 4, '2016-12-22');
insert into [CASEREVIEW] values ( 5, '2017-01-11');
insert into [CASEREVIEW] values ( 6, '2017-02-12');
insert into [CASEREVIEW] values ( 7, '2017-03-13');
insert into [CASEREVIEW] values ( 8, '2017-04-14');
insert into [CASEREVIEW] values ( 9, '2017-05-15');
insert into [CASEREVIEW] values (10, '2017-06-16');
insert into [CASEREVIEW] values (11, '2017-07-17');
insert into [CASEREVIEW] values (12, '2017-08-18');
So we can see the data from which it has to choose:
select CURRENT_TIMESTAMP as [Today];
select * from [CASEREVIEW];
And the actual query:
select [CASE_ID], [CASEOPENDATE] from [CASEREVIEW]
where MONTH(CONVERT(VARCHAR(10), [CASEOPENDATE], 120)) % 3 = MONTH(CONVERT(VARCHAR(10), CURRENT_TIMESTAMP, 120)) % 3
ORDER BY [CASEOPENDATE];
Results:
CASE_ID CASEOPENDATE
----------- ------------
3 2016-11-11
6 2017-02-12
9 2017-05-15
12 2017-08-18
(4 row(s) affected)