Possible to avoid repetition of expression in a QUERY - sql

I have to display time in a weird format.
For example, if time is 15:30:45.5000, I need to display "153045.5".
To do this, I have the following query:
SELECT LEFT(CONVERT(varchar(20), GETDATE(), 114), 2) +
SUBSTRING(CONVERT(varchar(20), GETDATE(), 114), 4, 2) +
SUBSTRING(CONVERT(varchar(20), GETDATE(), 114), 7, 2) + '.' +
SUBSTRING(CONVERT(varchar(20), GETDATE(), 114), 10, 1);
Is there anything I can do to avoid repeating the expression CONVERT(varchar(20), GETDATE(), 114)?
Edit:
I saw a really cool answer here which was deleted for some reason after I refreshed the page, but it gave me the idea to think of an alternative solution:
SELECT REPLACE(RIGHT(CONVERT(varchar(21), getdate(), 126), 10), ':', '')
Although this answer doesn't solve the original question in a generic way, it still solves my problem in a different way.

In addition to functions in other answers, you can calculate a partial result in a common table expression (CTE) or inline view:
; WITH gd(getDate_114)
AS (SELECT CONVERT(VARCHAR(20), GETDATE(), 114))
SELECT LEFT(getDate_114, 2)
+ SUBSTRING(gd.getDate_114, 4, 2)
+ SUBSTRING(gd.getDate_114, 7, 2)
+ '.'
+ SUBSTRING(gd.getDate_114, 10, 1)
FROM gd

Unfortunately, unless I'm mistaken, there isn't a way to minimize this in SQL Server 2008 R2. You'll have to construct it the way you're already doing it. Another option (as already pointed out by #jonasnas) would be to create a function that returns the format of the current date.
If you are able/willing to upgrade to SQL Server 2012, however, you can take advantage of the FORMAT() function to format the string:
Select Format(GetDate(), N'HHmmss.f')

Wrap all the formatting code in a function
create function dbo.FormatTime (#time datetime)
returns varchar(20)
as
begin
return (select LEFT(CONVERT(varchar(20), #time, 114), 2)
+ SUBSTRING(CONVERT(varchar(20), #time, 114), 4, 2)
+ SUBSTRING(CONVERT(varchar(20), #time, 114), 7, 4))
end
And use it as
select dbo.FormatTime(getdate())
To avoid repetition in the function body, you can store the #time converted to varchar in a variable
declare #dateAsVarchar varchar(20) = CONVERT(varchar(20), #time, 114)
return (select LEFT(#dateAsVarchar, 2)
+ SUBSTRING(#dateAsVarchar, 4, 2)
+ SUBSTRING(#dateAsVarchar, 7, 4))

Related

SQL Server 2012 - varchar to date

I am running views against a table that has dates stored as varchar(8) as DDMMYYYY, can someone please tell me how do I convert them to date format?
Thanks
In SQL Server 2012+, you can use datefromparts():
select datefromparts(right(col, 4) + 0, substring(col, 3, 2) + 0, left(col, 2) + 0)
I just added the + 0, because I'm not 100% sure if SQL Server will convert the arguments to integers.
Of course, you can also do it the "old" way as well:
select convert(date, right(col, 4) + substring(col, 3, 2) + left(col, 2))
SQL Server recognized the format YYYYMMDD as a valid date.

SQL: Error when converting varchar to datetime

WITH Valid_dates (ValidDate)
AS
(
SELECT '19' + SUBSTRING(column, 0, 3) + '-' + SUBSTRING(column, 3, 2) + '-' + SUBSTRING(column, 5, 2) AS ValidDate
FROM table
WHERE SUBSTRING(column, 3, 2) <= '12' --Max month
AND SUBSTRING(column, 3, 2) >= '01' --Min month
AND ISNULL(SUBSTRING(column, 3, 2), '') <> '' --Empty string
AND SUBSTRING(column, 5, 2) <= '31' --Max day
AND SUBSTRING(column, 5, 2) >= '01' --Min month
AND ISNULL(SUBSTRING(column, 5, 2), '') <> '' --Empty string
AND LEN('19' + SUBSTRING(column, 0, 3) + '-' + SUBSTRING(column, 3, 2) + '-' + SUBSTRING(column, 5, 2)) = 10 --Must match 10 character format
)
SELECT CONVERT(DATETIME, ValidDate)
FROM Valid_dates
When I execute this query in SQL Server Management Studio, I get the following error message: "The conversion of a varchar data type to a datetime data type resulted in an out-of-range value."
I have filtered out all invalid dates. Non-existent dates such as Feb 30, Apr 31, Jun 31 etc. are not filtered out per se as you can see, but I have checked for them, and they do not exist. Running only the CTE query yields plenty of results with which I can not find any discrepancies.
This is an issue with SQL Server. It does not guarantee the order of evaluation of clauses in the query. There is no sense that the where (even in the CTE) is evaluated "before" the rest of the query.
Note: This is a feature of the optimizer. By rearranging the evaluation of different components of the query, the optimizer can create a better query plan.
In SQL Server 2012+, the simplest method is TRY_CONVERT():
with . . .
select try_convert(datetime, validdate)
from valid_dates;
In earlier versions, you can use case:
select (case when <all your conditions here>
then convert(datetime, validdate)
end)
SQL Server does guarantee the sequential evaluation of case statements under normal circumstances (there are some quirky situations with aggregations), so this also fixes the problem.
I'm pretty sure that this is culture related.
You did not specify the actual input, from your code I suppose it is some unseparated format without a year like 920130 meaning the 30th of January in 1992?
This will be transformed in something like 1992-01-30.
Your default culture is probably one using something like yyyy-dd-mm which will lead into out-of-range error with a "month" higher than 12...
Try to use 102 as culture key:
SELECT CONVERT(DATETIME, ValidDate,102)
FROM Valid_dates
UPDATE
If my assumptions are true, it was much easier to try
SELECT TRY_CAST('19' + column AS DATE) FROM table
SQL Server allows natively to cast unseparated strings looking like yyyymmdd. Using TRY_CAST will return NULL if the cast is not possible.
With older versions (<2012) use this
SELECT CASE WHEN ISDATE('19' + column)=1 THEN CAST('19' + column AS DATE) ELSE NULL END FROM table

What is the best way to write the date in mm-mm-yyyy in SQL

I'd like to return a date from SQL in the following format 2011-12-DEC, 2012-01-JAN, 2012-02-FEB, 2012-03-MAR etc...
Currently I have the below code, but don't think it's the best. It also does not return a 0 in front of the month (i.e. 8 rather than 08)
print CONVERT(VARCHAR(20), DATEPART(yyyy,GETDATE())) + '-'+ CONVERT(VARCHAR(20), DATEPART(mm,GETDATE()))
For SQL Server, something like this
select convert(varchar(8), getdate(),120)
+ convert(varchar(3),datename(month,getdate()))
For Oracle use TO_CHAR and date formatting. For Example
SELECT TO_CHAR(SYSDATE, 'YYYY-DD-MON') FROM DUAL
There is a wide range of possible date format strings
See here.
If you really do want yyyy-mm-mmm then you could get it like so (for SQL server):
select substring(convert(nvarchar, getdate(), 120), 1, 7)
+ '-' +
substring(upper(datename(mm, getdate())), 1, 3)
Consider a DATE_FORMAT function or the like, depending on your RDMS.
Well,
you should use a formatter (eg AS [DD/MM/YYYY] ).
All of them are listed here including your requirement for "month" naming
http://www.sql-server-helper.com/tips/date-formats.aspx
SELECT SUBSTRING(CONVERT(VARCHAR(11), GETDATE(), 113), 4, 8) AS [Mon-YYYY]
would give you Apr-2006
just turn it around as you like.

Add characters in the variable

I need to make the string/varchar variable with value 20061212 to be string/varchar value 2006-12-12 00:00:00
I can't find the right SQL syntax code to make it happened in SQL Server.
The code can be created as stored procedure or similar in SQL Server.
SELECT
LEFT(#string, 4)
+ '-' + SUBSTRING(#string, 5, 2)
+ '-' + SUBSTRING(#string, 7, 2)
+ ' 00:00:00'
You could cast your string to a DATETIME and then convert it back to a string in your chosen format. But that would likely be slower than this more explicit option.
SELECT
CONVERT(VARCHAR(19), CAST(#string AS DATETIME), 120)
You can use stuff
declare #s varchar(8) = '20061212'
select stuff(stuff(#s, 7, 0, '-'), 5, 0, '-')+' 00:00:00'
You can use the SUBSTRING() function (detailed here: http://www.sql-statements.com/sql-substring.html) to take apart the original string, and then put the pieces back together with the added dashes & time at the end using the concatenation operator +.
Culture independent variant:
SELECT CONVERT(varchar, convert(datetime, '20061212', 112), 120)
BUT this only valid for DATETIME-allowed range of dates, use DATETIME2 instead

SQL Server String Parsing

I have SQL Server 2005 and all dates are stored using a DATETIME column type. The front-end application handles dates in a "yyyyMMdd hhmmss" format. I'm writing a set of SQL queries and stored procedures and was wondering if there is an easy way to convert this format to the standard SQL DATETIME. I did not code the front-end app so I cannot make any changes to it.
I have looked into CONVERT(), but none of the type codes match what I want. The closest one is
CONVERT(DATETIME, '20101017' 112)
But that does not have the time component of the input. Any ideas? or do I have to write a SQL function to do that parsing and conversion.
Thank you,
If you insert the colons into the appropriate places in your time, you can use style 120.
declare #d varchar(15)
set #d = '20101017 111428'
select CONVERT(DATETIME, stuff(stuff(#d,12,0,':'),15,0,':'), 120)
You might find this page to be useful (if you can get past the psychosis-inducing color scheme).
How about this:
declare #s as varchar(25)
set #s = '20101109 172054'
select #s, convert(datetime, SUBSTRING(#s, 1, 4) + '-' + SUBSTRING(#s, 5, 2)
+ '-' + SUBSTRING(#s, 7, 3) + SUBSTRING(#s, 10, 2) + ':'
+ SUBSTRING(#s, 12, 2) + ':' + SUBSTRING(#s, 14, 2), 20)