SQL Server: how to add case statement to select - sql

I am using the following select to query a date from a database table.
The input (ms) for this query results from an xml string and the stored procedure then loops through all the single values in the xml to return a certain number (integer) for each of them.
This works fine so far.
Is there a way that I can return a placeholder number (like 99999) if the input (ms) is empty / nothing ?
Currently the below returns 0 in such a case which I cannot use to identify this as 0 can also be a valid result in other cases.
My stored procedure so far:
SELECT ms as date,
type,
(
SELECT COUNT(calendar_dt)
FROM Calendar
WHERE day_of_week NOT IN (1, 7)
AND calendar_dt > GETDATE()
AND calendar_dt <= ms
) as bDays
FROM #dates
FOR XML PATH('ms'), ELEMENTS, TYPE, ROOT('ranks')
Many thanks in advance for any help with this, Tim.

If the column "ms" is actually NULL or populated, just use ISNULL.
http://technet.microsoft.com/en-us/library/ms184325.aspx
SELECT ISNULL(ms, 99999) AS date
However, if that column can contain an empty string, which is not the same as NULL, then also use NULLIF.
http://technet.microsoft.com/en-us/library/ms177562.aspx
SELECT ISNULL(NULLIF(ms,''), 99999) AS date

Related

SQl Server Converting to Date fails , DateTime works

I have a table with a varchar(25) column that holds a date value. A typical value is '11/04/2017'.
This query returns 0 rows
select *
from myTable
where isdate(inputDate) = 0
I am trying to find a max on this, using a date sort.
This query returns the expected result
;with gooddates as
(
select
medcomfolder, PatientId, PatientBirthday, InputDate
from
myTable
where
isdate(inputDate) = 1
)
select max(convert(datetime, inputDate))
from gooddates
This query returns an error.
;with gooddates as
(
select
medcomfolder, PatientId, PatientBirthday, InputDate
from
dwhFuData
where
isdate(inputdate) = 1
)
select max(convert(date, inputdate))
from gooddates
This is the returned error
Msg 241, Level 16, State 1, Line 274
Conversion failed when converting date and/or time from character string
The difference between the 2 queries is that the first is converting to a dateTime while the latter is converting to a date.
At this point, I can move forward w/ the dateTime option, but I am left wondering what I am missing.
I have checked that there are no embedded spaces, and all the columns have a len(InputDate) = 10 (there is NO time data included)
I selected distinct values,put them in excel, and did a date function on each row. I was hoping to get a #VALUE on 1 row. All the rows worked.
So there is nothing silly like '02/31/2019' going on.
How can a dateTime conversion pass when a simple date conversion does not?
My guess is that you have values that include a time stamp following the date (based on the fact that isdate() is always zero).
If so, one simple solution would be to use convert(date, left(inputdate, 10)). Another solution uses try_convert():
try_convert(date, inputdate)
To find the offending values:
select inputdate
from dwhFuData
where try_convert(date, inputdate) is null and inputdate is not null;

How to improve performance of extracting date and time from string in SQL Server 2008R2?

I am working on a data migration task (SSIS), using SQL 2008 database where I have to extract the date and time from a string and convert it into a datetime data type field to be able to insert later in a table.
I do have a SQL function saved in the database which I am using in a query and it is parsing the string correctly to output the correct results. The only major problem is that the query is taking about an hour and half to get some 120,000 records. If I can be please pointed to the right direction as to if I need to correct my query or function to improve performance significantly.
The query where I am using the string parsing function (fnExtrDateTimeFromString) is
select
case when dbo.fnExtrDateTimeFromString(NoteList.Item) is null then CAST('2000-01-01 00:00:00.000' as datetime)
when CAST(dbo.fnExtrDateTimeFromString(NoteList.Item) as date) = CAST('1900-01-01' as date) then dbo.fnExtrDateTimeFromString(NoteList.Item)+CAST('2000-01-01 00:00:00.000' as datetime)
else dbo.fnExtrDateTimeFromString(NoteList.Item) end as NoteDate,
CAST(LTRIM(RTRIM(NoteList.Item)) as text) as UsersNotes
from UserNotes
cross apply convDelimitedSplit(UserNotes.NoteText,',') as NoteList
where LEN(ISNULL(UserNotes.Notes,'')) > 0
Inside the fnExtrDateTimeFromString function, I am using 2 table variables to store all the patterns of date and time format and then using patindex to later concatenate both the string of the date & time, and concatenate to a datetime field. It is 300 something line function which I am not aware I can paste here.
An example of the string is 'User appt:7/27/94# 10:30AM', and the date would be 07/27/1994 and time 10:30. These are user input strings, so they are very inconsistent regarding spaces and separating characters.
As #Shnugo has pointed out you are calling this "expensive" function multiple times for each row.
To ensure only one call is made use sub-query:
select
case when NoteDate is null then CAST('2000-01-01 00:00:00.000' as datetime)
when NoteDate = CAST('1900-01-01' as date) then NoteDate + CAST('2000-01-01 00:00:00.000' as datetime)
else NoteDate
end as NoteDate,
UsersNotes
from
( select
dbo.fnExtrDateTimeFromString(NoteList.Item) as NoteDate,
CAST(LTRIM(RTRIM(NoteList.Item)) as text) as UsersNotes
from UserNotes
cross apply convDelimitedSplit(UserNotes.NoteText,',') as NoteList
where LEN(ISNULL(UserNotes.Notes,'')) > 0 ) as a
Note: text data type is deprecated, you should use VARCHAR( MAX )
Provided this date splitting function is the performance bottleneck, it should double/tripple the performance.
Good Read: https://sqlperformance.com/2014/06/t-sql-queries/dirty-secrets-of-the-case-expression

Find data with specific date and month only

I am trying to find a data with specific where clause of date and month but I am receiving an error can anyone help me with this?
select *
from my_data
where date BETWEEN '11-20' AND '12-15'
MS SQL Server Management Studio
I am receving an error
Conversion failed when converting date and/or time from character string
Most databases support functions to extract components of dates. So, one way of doing what you want is to convert the values to numbers and make a comparison like this:
where month(date) * 100 + day(date) between 1120 and 1215
The functions for extracting date parts differ by database, so your database might have somewhat different methods for doing this.
The conversion is failing because you are not specifying a year. If you were to specify '11-20-2015' your query would work just insert whatever year you need.
SELECT *
FROM my_data
WHERE date BETWEEN '11-20-2015' AND '12-15-2015'
Alternatively if you wanted data from that range of dates for multiple years I would use a while loop to insert information in a # table then read from that table, depending on the amount of data this could be quick or sloooowww here is an example.
DECLARE #mindatestart date, #mindateend date, #maxdatestart date
SET #mindatestart = '11-20-2010'
SET #mindateend = '12-15-2010'
SET #maxdatestart = '11-20-2015'
SELECT top 0 *, year = ' '
INTO #mydata
FROM my_data
WHILE #mindatestart < #maxdatestart
BEGIN
INSERT INTO #mydata
SELECT *, YEAR(#mindatestart)
FROM my_data
where date between #mindatestart and #mindateend
SET #mindatestart = DATEADD(Year, 1, #mindatestart)
SET #mindateend = DATEADD(Year, 1, #mindateend)
END
This will loop and insert the data from 2010-2015 for those date ranges and add a extra column on the end so you can call the data and order by year if you want like this
SELECT * FROM #mydata order by YEAR
Hopefully some part of this helps!
FROM THE COMMENT BELOW
SELECT *
FROM my_data
WHERE DAY(RIGHT(date, 5)) between DAY(11-20) and DAY(12-15)
The reason '11-20' doesn't work is because its a character string which is why you have to input it between ' ' What the Month() function does is take whatever you put between the () and convert it to an integer. Which is why you're not getting anything back using the method in the first answer, the '-Year' from the table date field is being added into the numeric value where your value is just being converted from 11-20 you can see by using these queries
SELECT MONTH(11-20) --Returns 12
SELECT MONTH(11-20-2015) -- Returns 6
SELECT MONTH(11-20-2014) -- Returns 6
Using RIGHT(Date, 5) you only get Month-day, then you date the day value of that so DAY(RIGHT(DATE, 5) and you should get something that in theory should fall within those date ranges despite the year. However I'm not sure how accurate the data will be, and its a lot of work just to not add an additional 8 characters in your original query.
Since you only care about month and day, but not year, you need to use DATEPART to split up the date. Try this:
select *
from my_data
WHERE 1=1
AND (DATEPART(m, date) >= 11 AND DATEPART(d,date) >= 20)
AND (DATEPART(m, date) <= 12 AND DATEPART(d,date) <= 15)

Convert String to date in select statement

I have a column which contains data but the problem is that this column has data type of varchar(50) and it has to be this due to some reasons,now what i want to do is while selecting data from table , i want to treat this column as date so that i can use it in where clause. i am using the code below for converting it yo date , but it converts some values and then gives an error
this is my sample data
8/1/2002
6/9/2001
14/9/2001
26/7/2001
14/12/2001
21/1/2002
29/4/2001
7/5/2001
9/11/2001
16/7/2001
select CONVERT(date,sowingDate,103) from tblAgriculture_staging
I have tried which differnt version of date format e.g 103,105 etc
but still it converts some values but error comes on some values and query execution stops
Try this:
SET DATEFORMAT dmy;
select case when isdate(sowingDate) = 1 then CONVERT(date,sowingDate,103) end [date] from tblAgriculture_staging
or (if you are using sql 2012)
SET DATEFORMAT dmy;
select case when TRY_CONVERT(date, sowingDate) IS NOT NULL then CONVERT(date,sowingDate,103) end [date] from tblAgriculture_staging
but this solution hides (convert to NULL) all dates that are wrong. You can reverse the condition first and find/fix all rows with incorrect date (i.e. 31/02/2013) and then use this queries to show only valid dates
SQLFiddle
but it converts some values and then gives an error this is my sample
data
because some data are in invalid format or contains incorrect symbols.
Try this:
select CONVERT(date,ltrim(rtrim(sowingDate)), 103) from tblAgriculture_staging
or examine your values:
select ISDATE(sowingDate) as IsDate, sowingDate, CASE WHEN ISDATE(sowingDate)=1 THEN CONVERT(date,ltrim(rtrim(sowingDate)), 103) ELSE NULL END from tblAgriculture_staging
This is slightly crappy, but so is storing dates as varchar.
this is code that has worked for me in the past where i had some dates with 4 digit years and some with 2 digit years.
where (TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),1)>=#From
AND TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),1)<=#To)
OR (TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),101)>=#From
AND TRY_CONVERT(Datetime2,LTRIM(RTRIM([INVC DTE])),101)<=#To)
SQL Server 2012 + Only
This assumes you have cleaned up anything that actually just isn't a date...
This will return all the dates that are not actually dates.
select sowingDate from tblAgriculture_staging where isdate(sowingDate)=0

SQL: Convert String of MMMDD to Datetime

I have a nvarchar(5) column of data that is formatted MMMDD (for example, OCT26). With my select statement, I'd like to convert it to a datetime data type with the current year, and then save that datetime value as an alias, say, UsefulDate. So something like 10-26-2012.
Something like: SELECT (whatever SQL gets the job done) AS UsefulDate
The exact formatting doesn't matter; I just need to be able to compare two dates together with greater than and less than operators. Also, sometimes the column will be blank. In that case, I'd like to set the alias to blank as well. Is this possible?
Thanks for your help!
You can convert varchar fields in format MMMDD to date with current year with :
select convert(datetime,'OCT26'+','+cast(year(getdate()) as varchar),107)
So your query would be something like :
select convert(datetime,case varcharDate when '' then null else varcharDate end +
','+cast(year(getdate()) as varchar),107) as UsefulDate
from table
select CASE WHEN ISDATE(mmmdd+' '+right(year(getdate()),4)) = 1
THEN CAST(mmmdd+' '+right(year(getdate()),4) as datetime)
END UsefulDate, *
from tbl