Related
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;
I need to extract the date (08-01-2021) from the below string that has no whitespace
select 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' from dual
I tried to apply the REGEXP_SUBSTR function as shown below, but using this query I just removed 'Date-'
with x as
(select 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' as str
from dual)
SELECT REGEXP_SUBSTR(STR, 'Date-([^ ]+)',1,1,'i',1)
FROM x;
Please advise
You are zero-padding the date values so each term has a fixed length and have a fixed prefix so you do not need to use (slow) regular expressions and can just use simple string functions:
SELECT TO_DATE(SUBSTR(value, 6, 10), 'DD-MM-YYYY')
FROM table_name;
(Note: if you still want it as a string, rather than as a date, then just use SUBSTR without wrapping it in TO_DATE.)
For example:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(SUBSTR(value, 6, 10), 'DD-MM-YYYY') AS date_value
FROM table_name;
Outputs:
DATE_VALUE
08-JAN-21
db<>fiddle here
If the Date- prefix is not going to always be at the start then use INSTR to find it:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL UNION ALL
SELECT 'Trans-1000008-Date-08-02-2021-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(SUBSTR(value, INSTR(value, 'Date-') + 5, 10), 'DD-MM-YYYY') AS date_value
FROM table_name;
Which outputs:
DATE_VALUE
08-JAN-21
08-FEB-21
If you can have multiple Date- substrings and you want to find the one that is either at the start of the string or has a - prefix then you may need regular expressions:
WITH table_name ( value ) AS (
SELECT 'Date-08-01-2021-Trans-1000008-PH.0000-BA-CR-9999.21' FROM DUAL UNION ALL
SELECT 'TransDate-1000008-Date-08-02-2021-PH.0000-BA-CR-9999.21' FROM DUAL
)
SELECT TO_DATE(
REGEXP_SUBSTR(value, '(^|-)Date-(\d\d-\d\d-\d{4})([-.]|$)', 1, 1, 'i', 2),
'DD-MM-YYYY'
) AS date_value
FROM table_name;
db<>fiddle here
Just use a more precise regular expression:
SELECT REGEXP_SUBSTR(STR, 'Date-([0-9]{2}-[0-9]{2}-[0-9]{4})', 1, 1, 'i', 1)
FROM x;
Or for less accuracy but more conciseness:
SELECT REGEXP_SUBSTR(STR, 'Date-([-0-9]{10})', 1, 1, 'i', 1)
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.
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.
This question already has answers here:
How to convert datetime string without delimiters in SQL Server as datetime?
(6 answers)
Closed 6 years ago.
I want to convert below string to DateTime in SQL.
20140601152943767
I know convert(date,'20140601152943767') this but I want time part also.
Above function only returns me Date part.
Thanks in advance.
I would use following solution:
SELECT CONVERT(DATETIME, STUFF(STUFF(STUFF(STUFF('20140601152943767', 9, 0, ' '), 12, 0, ':') , 15, 0, ':'), 18, 0, '.'))
Note #0: All those STUFF calls will convert source strings from 20140601152943767 to 20140601 15:29:43.767.
Note #1: SELECT STUFF('abcef', 4, 1, 'DDD') will replace substring starting from index 4 with a length of 1 char (e) with DDD -> abcDDDf
Note #2: SELECT STUFF('abcef', 4, 0, 'DDD') returns abcDDDef
You can try lik ethis:
select
concat(convert(date,LEFT('20140601152943767',8)), ' ' , Convert(time,Dateadd(SECOND,
Right('20140601152943767',2)/1,
Dateadd(MINUTE,
Right('20140601152943767',4)/100,
Dateadd(hour,
Right('20140601152943767',6)/10000,
'1900-01-01')))) )
as myDate
Output:
2014-06-01 22:38:07.0000000
Well, first of all - you need conversion not to date but to datetime type.
Second - you should always specify format as mentioned:
https://msdn.microsoft.com/en-us/library/ms187928(v=sql.120).aspx
e.g.
select convert(datetime, '20140501', 112)
3 - there is no such format supported for your value demonstrated, so you have to modify your value yo something like yyyy-mm-ddThh:mi:ss.mmm (iso) or to make custom conversion with substring and so on.
;WITH myvalues AS (
SELECT '20140601152943767' value
)
SELECT
convert(date, LEFT(mv.value, 8), 112),
cast(STUFF(STUFF(STUFF(STUFF(mv.[value], 1, 8, ''), 7, 0, '.'), 5, 0, ':'), 3, 0, ':') AS TIME)
FROM myvalues mv
Try This one
declare #datetime varchar(20) = '20140601152943767'
select convert(varchar(20),convert(date,LEFT(#datetime,8))) + ' ' + substring(RIGHT(#datetime,9), 1, 2)
+ ':' + substring(RIGHT(#datetime,9), 3, 2)
+ ':' + substring(RIGHT(#datetime,9), 5, 2)
+ '.' + substring(RIGHT(#datetime,9), 7, 3)
I know some might argue that this is not the best way , but still it's an alternative.Few people have already used convert and stuff functions .
Try this out.Easy to understand.Also test your subqueries.
select y1||'-'||M1||'-'||d1||' '||h1||':'||mi||':'||s1||':'||f1 as xdate
from
(
select substr('20140601152943767',1,4) Y1 from dual
),
(
select substr('20140601152943767',5,2)M1 from dual
),
(
select substr('20140601152943767',7,2) d1 from dual
),
(
select substr('20140601152943767',9,2) h1 from dual
),
(
select substr('20140601152943767',11,2) mi from dual
),
(
select substr('20140601152943767',13,2) s1 from dual
),
(
select substr('20140601152943767',15,3) f1 from dual
)
Output:
2014-06-01 15:29:43.767