Convert NULL datetime to Blank - sql

I would like to convert a datetime field to varchar so I can show a blank or a message when the date is NULL.
This is what I have so far:
select
isnull(us.Date,0) as USDate,
isnull(au.Date,0) as AUDate
from ustable us
left join autable au
on us.column=au.column
Right now this is showing:
USDATE
2014-10-24 10:29:07.450
1900-01-01 00:00:00.000
I would like to be able to make the "1900-01-01 00:00:00.000" varchar so I can write a message or show a true blank.

The simplest line of code I've found for what you're trying to accomplish is as follows.
ISNULL(CONVERT(VARCHAR(30),us.Date,121),'') as USDate,
ISNULL(CONVERT(VARCHAR(30),au.Date,121),'') as AUDate,
I have tested this and verified that it works.

You can use Case AND CONVERT like this -
SELECT
CASE WHEN us.Date IS NULL THEN '' ELSE CONVERT(VARCHAR(30), us.Date, 121) END AS USDate,
CASE WHEN au.Date IS NULL THEN '' ELSE CONVERT(VARCHAR(30), au.Date, 121) END AS AUDate
FROM ustable us
left join autable au
on us.column=au.column

To do it in SQL:
Change your SELECT statement to incorporate a WHEN...THEN clause:
CASE us.Date
WHEN '1900-01-01 00:00:00.000' THEN ''
WHEN NULL THEN ''
ELSE us.Date
END as USDate,
CASE au.Date
WHEN '1900-01-01 00:00:00.000' THEN ''
WHEN NULL THEN ''
ELSE au.Date
END as AUDate
If you have front-end code, then you could just implement the functionality on the front-end without changing your SQL code.

Given a column defined like this:
date_of_birth datetime null
You can simply say
select date_of_birth = coalesce( convert(varchar(32),date_of_birth) , '' )
from some_table_with_a_nullable_datetime_column

You can use the NVL() function ...
You can use the NVL function to convert an expression that evaluates
to NULL to a value that you specify. The NVL function accepts two
arguments: the first argument takes the name of the expression to be
evaluated; the second argument specifies the value that the function
returns when the first argument evaluates to NULL. If the first
argument does not evaluate to NULL, the function returns the value of
the first argument.
For example:
select
nvl(us.Date,'') as USDate,
nvl(au.Date,'') as AUDate
from ustable us
left join autable au
on us.column=au.column
Or put anything you want as the Default:
select
nvl(us.Date,'this was a NULL') as USDate,
nvl(au.Date,'this was a NULL') as AUDate
from ustable us
left join autable au
on us.column=au.column

Try something like this...
select
CONVERT(varchar(50), isnull(us.Date,0)) as USDate,
CONVERT(varchar(50), isnull(au.Date,0)) as AUDate
from ustable us
left join autable au
on us.column=au.column
You'll want to change the size of the varchar depending upon your date format. Also, CONVERT takes a third parameter that will allow you to change the format of your string.

select null USDate, NUll AUDate
from ustable us
left join autable au on us.column=au.column
It's work try it, it will show column value should be null.

Related

Alternative to cast function in join when it comes to stored proc optimisation?

What is the best alternative for cast function used to convert datatype in SQL query inside stored proc where join is used?
I have read often that its not good to use function and need help with optimization of query below.
SELECT
A.DATE,
A.Value curr ,
ISNULL( CAST( CONVERT ( DECIMAL(18,4), CASE WHEN #INV = 0 THEN NULLIF(ISNULL(tblRate.currBid,0),0) ELSE 1.00 / NULLIF(ISNULL(tblRate.currBid,0) ,0) END ) AS VARCHAR) ,#TempHardcodeValue) AS currBid,
A.Value +' - '+ A.currName As ConcatenatedCurr
FROM #TEMPTable A
LEFT JOIN tblCurrRates (NOLOCK) tblRate ON A.Date = cast(tblRate.currDate as date) AND A.currCode = tblRate.currCode
ORDER BY A.Date ,A.Value
As you can see cast function is used, so is there any other way to reqrite without cast?
Actually, SQL Server is probably okay with the cast. The one exception to using functions is casting date/times to dates -- SQL Server recognizes the conversion for the use of indexes.
But, you can do:
FROM #TEMPTable A LEFT JOIN
tblCurrRates r
ON r.currDate >= A.Date AND
r.currDate < DATEADD(day, 1, A.Date) AND
r.currCode = a.currCode
This would allow the code to use an index on tblCurrRates(currCode, currDate). I suspect, though, that your code would also use that index.

SQL Query with between two dates showing even those not between

select ktl.id, kth.trans_dte, kth.trtype, kp.match_code,ktl.net_amount,ktl.gross_amount,ktl.db_portfolio_type,ktl.cr_portfolio_type from k$transaction_lines ktl
left join k$transaction_header kth on ktl.id=kth.id
left join k$portfolio kp on kp.id = (CASE WHEN ktl.db_portfolio_type = 'C' THEN ktl.db_portfolio ELSE ktl.cr_portfolio END)
where to_char(kth.trans_dte,'DD-MON-YY') >= '22-AUG-16'
and to_char(kth.trans_dte,'DD-MON-YY') <= '27-AUG-16'
and ktl.db_portfolio_type <> 'I'
and ktl.cr_portfolio is not null
order by kth.trans_dte, ktl.id, kp.match_code, kth.trtype
This is my query. I just want to know if I have something wrong with my where clause kth.trans_dte.
I only want to get Transactions from August 22 to Aug 27 but it I am getting transactions before that date, february and march are included when they shouldn't be. I wonder why.. Is there a problem with my code or is it something with the db that I don't know. Thanks!
you convert your field to char with to_char and then try to compare it datewise. to_char does exactly what it says - converts to a char string so you'll get dates according to ascii representation of the string
try using to_date instead - on both sides of the condition (s)
try using BETWEEN instead of 2 conditions .
select ktl.id, kth.trans_dte, kth.trtype, kp.match_code,ktl.net_amount,ktl.gross_amount,ktl.db_portfolio_type,ktl.cr_portfolio_type from k$transaction_lines ktl
left join k$transaction_header kth on ktl.id=kth.id
left join k$portfolio kp on kp.id = (CASE WHEN ktl.db_portfolio_type = 'C' THEN ktl.db_portfolio ELSE ktl.cr_portfolio END)
where (to_char(kth.trans_dte,'DD-MON-YY') >= '22-AUG-16'
and to_char(kth.trans_dte,'DD-MON-YY') <= '27-AUG-16')
and ktl.db_portfolio_type <> 'I'
and ktl.cr_portfolio is not null
order by kth.trans_dte, ktl.id, kp.match_code, kth.trtype
Try this.
try using between Keyword and to_date function in Query like
where kth.trans_dte between to_date('22-AUG-16')
and to_date('27-AUG-16')
and ktl.db_portfolio_type <> 'I'
and ktl.cr_portfolio is not null
order by kth.trans_dte, ktl.id, kp.match_code, kth.trtype
Sorry, I solved it just now. I can't use to_char when doing that condition that is why it gives the wrong results.

SQL Server DATE conversion error

Here is my query:
SELECT
*
FROM
(SELECT
A.Name, AP.PropertyName, APV.Value AS [PropertyValue],
CONVERT(DATETIME, APV.VALUE, 101) AS [DateValue]
FROM dbo.Account AS A
JOIN dbo.AccountProperty AS AP ON AP.AccountTypeId = A.AccountTypeId
JOIN dbo.AccountPropertyValue AS APV ON APV.AccountPropertyId = APV.AccountPropertyId
AND APV.AccountId = A.AccountId
WHERE
A.AccountTypeId = '19602AEF-27B2-46E6-A068-7E8C18B0DD75' --VENDOR
AND AP.PropertyName LIKE '%DATE%'
AND ISDATE(APV.Value) = 1
AND LEN(SUBSTRING( REVERSE(APV.Value), 0 , CHARINDEX( '/', REVERSE(APV.Value)))) = 4 --ENSURE 4 digit year
) AS APV
WHERE
APV.DateValue < GETDATE()
It results in the following error:
Conversion failed when converting date and/or time from character string.
If you comment out the WHERE APV.DateValue < GETDATE() clause then there is no error and I get the 300+ rows. When I enable the WHERE clause I get the error.
So you are going to tell me my data is jacked up right? Well that's what I thought, so I tried to figure out where the problem in the data was, so I started using TOP() to isolate the location. Problem was once I use the TOP() function the error went away, I only have 2000 rows of data to begin with. So I put a ridiculous TOP(99999999) on the inner SELECT and now the entire query works.
The inner SELECT returns the same number of rows with or without the TOP().
WHY???
FYI, this is SQL that works:
SELECT
*
FROM
(SELECT TOP(99999999)
A.Name, AP.PropertyName, APV.Value AS [PropertyValue],
CONVERT(DATETIME, APV.VALUE, 101) AS [DateValue]
FROM dbo.Account AS A
JOIN dbo.AccountProperty AS AP ON AP.AccountTypeId = A.AccountTypeId
JOIN dbo.AccountPropertyValue AS APV ON APV.AccountPropertyId = APV.AccountPropertyId
AND APV.AccountId = A.AccountId
WHERE
A.AccountTypeId = '19602AEF-27B2-46E6-A068-7E8C18B0DD75' --VENDOR
AND AP.PropertyName LIKE '%DATE%'
AND ISDATE(APV.Value) = 1
AND LEN(SUBSTRING(REVERSE(APV.Value), 0 , CHARINDEX( '/', REVERSE(APV.Value)))) = 4
) AS APV
WHERE
APV.DateValue < GETDATE()
The problem that you are facing is that SQL Server can evaluate the expressions at any time during the query processing -- even before the WHERE clause gets evaluated. This can be a big benefit for performance. But, the consequence is that errors can be generated by rows not in the final result set. (This is true of divide-by-zero as well as conversion errors.)
Fortunately, SQL Server has a work-around for the conversion problem. Use try_convert():
TRY_CONVERT( DATETIME, APV.VALUE, 101) AS [DateValue]
This returns NULL rather than an error if there is a problem.
The reason why some versions work and others don't is because of the order of execution. There really isn't a way to predict what does and does not work -- and it could change if the execution plan for the query changes for other reasons (such as table statistics). Hence, use try_convert().
My guess is that your date is such that APV.VALUE contains also data that cannot be converted into a date, and should be filtered out using the other criteria?
Since SQL Server can decide to limit the data first using the criteria you have given:
APV.DateValue < CONVERT( DATETIME, GETDATE(),101)
And if there is data that cannot be converted into the date, then you will get the error.
To make it more clear, this is what is being filtered:
CONVERT( DATETIME, APV.VALUE, 101) AS [DateValue]
And if there is any data that cannot be converted into a date using 101 format, the filter using getdate() will fail, even if the row would not be included in the final result set for example because AP.PropertyName does not contain DATE.
Since you're using SQL Server 2012, using try_convert instead of convert should fix your problem
And why it works with top? In that case SQL Server cannot use the criteria from the outer query, because then the result might change, because it might affect the number of rows returned by top
Because number of records in the table < 999..99. And regarding the error it seems like SQL engine evaluates the WHERE clause after converting to date so you can try this:
SELECT *
FROM (
SELECT A.Name
, AP.PropertyName
, APV.Value AS [PropertyValue]
,
CASE
WHEN SDATE(APV.Value) = 1
THEN CONVERT( DATETIME, APV.VALUE, 101)
ELSE NULL
END AS [DateValue]
FROM dbo.Account AS A
JOIN dbo.AccountProperty AS AP
ON AP.AccountTypeId = A.AccountTypeId
JOIN dbo.AccountPropertyValue AS APV
ON APV.AccountPropertyId = APV.AccountPropertyId
AND APV.AccountId = A.AccountId
WHERE A.AccountTypeId = '19602AEF-27B2-46E6-A068-7E8C18B0DD75' --VENDOR
AND AP.PropertyName LIKE '%DATE%'
AND LEN( SUBSTRING( REVERSE(APV.Value), 0 , CHARINDEX( '/', REVERSE(APV.Value)))) = 4 --ENSURE 4 digit year
) AS APV
WHERE APV.DateValue IS NOT NULL AND APV.DateValue < GETDATE()

T-SQL: Check if date is in proper format within Where-Clause

How is it possible to check within the where-clause, if the date parameter is set and if it's in the proper format (dd/mm/yyyy).
Here is my SP with parameter #birthdaysearch in format (dd/mm/yyyy):
Select *
From Clients as c
WHERE
CASE ISDATE(#birthdaysearch)
WHEN 0 THEN (c.BirthDay LIKE '%')
WHEN 1 THEN (c.BirthDay LIKE CONVERT(datetime,#birthdaysearch,103))
END
Why isn't that working?
Thanks for your help!
You have incorrect syntax:
Select *
From Clients as c
WHERE ISDATE(#birthdaysearch) = 0 OR
(ISDATE(#birthdaysearch) = 1 AND c.BirthDay LIKE CONVERT(datetime, #birthdaysearch, 103))
or:
Select *
From Clients as c
WHERE c.BirthDay LIKE CASE WHEN ISDATE(#birthdaysearch) = 0 THEN '%'
ELSE CONVERT(datetime, #birthdaysearch, 103) END
But it is very strange why are you comparing dates with LIKE?
I suggest you the following:
Select *
From Clients as c
WHERE c.BirthDay = CASE ISDATE(#birthdaysearch) WHEN 0 THEN c.BirthDay
ELSE CAST(#birthdaysearch AS DATE) END
Given the conversation in the comments, I think the following would be appropriate:
Select *
From Clients as c
WHERE COALESCE(#BirthDaySearch, c.BirthDay) = c.BirthDay
So, given that your parameter is a datetime type, and is nullable, there is no need to check the date format, as it will always be valid (or null) when it hits the sproc.

SQL Server Case Statement when IS NULL

I'm trying to do an IF statement type function in SQL server.
Where there is a NULL in the field, I want it to take a field from one of the tables and add 10 days to it.
And if possible create another column and add the 30 days.
SELECT DISTINCT
B.[ID],
MAX(A.[START DATE]),
B.[STAT],
C.[POST DATE],
CASE
WHEN (C.[POST DATE] BETWEEN C.[EVENT DATE]+10 AND C.[EVENT DATE]+30) THEN 'GOOD'
END AS [BETTER VISIT],
CASE
WHEN B.[STAT] IS NULL THEN (C.[EVENT DATE]+10)
ELSE '-'
END AS [DATE]
FROM
#TEMP1 A
FULL OUTER JOIN #TEMP2 B
ON A.[ID]=B.[ID]
FULL OUTER JOIN #TEMP3 C
ON A.[ID]=C.[ID]
GROUP BY
B.[ID],
B.[STAT],
C.[POST DATE],
C.[EVENT DATE]
ORDER BY
A.[START DATE] DESC
The result would look sort of like:
ID START DATE STAT POST DATE BETTER VISIT DATE DATE2
---------------------------------------------------------------------------
1 2013-01-01 GOOD 2013-11-01 GOOD - -
2 2013-03-01 NULL NULL NULL 2013-03-11 2013-03-31
CASE WHEN B.[STAT] IS NULL THEN (C.[EVENT DATE]+10) -- Type DATETIME
ELSE '-' -- Type VARCHAR
END AS [DATE]
You need to select one type or the other for the field, the field type can't vary by row.
The simplest is to remove the ELSE '-' and let it implicitly get the value NULL instead for the second case.
I agree with Joachim that you should replace the hyphen with NULL. But, if you really do want a hyphen, convert the date to a string:
(CASE WHEN B.[STAT] IS NULL
THEN convert(varchar(10), C.[EVENT DATE]+10, 121)
ELSE '-'
END) AS [DATE]
Also, the distinct is unnecessary in your select statement. The group by already does this for you.
You can use IIF (I think from SQL Server 2012)
SELECT IIF(B.[STAT] IS NULL, C.[EVENT DATE]+10, '-') AS [DATE]
case isnull(B.[stat],0)
when 0 then dateadd(dd,10,(c.[Eventdate]))
end
you can add in else statement if you want to add 30 days to the same .
In this situation you can use ISNULL() function instead of CASE expression
ISNULL(B.[STAT], C.[EVENT DATE]+10) AS [DATE]
Your hyphen in your ELSE statement isn't accepted in the column which is being defined under the datetime data type. You could either:
a) Wrap a CAST around your [stat] field to convert it to a varchar representation of a date
b) Use a datetime like 9999-12-31 for your ELSE value.
Take a look at the ISNULL function. It helps you replace NULL values for other values. http://msdn.microsoft.com/en-us/library/ms184325.aspx
Slight variation on Mahesh solution for mssql:
case when isnull(B.[stat],0) = 0
then dateadd(dd,10,(c.[Eventdate]))
end