February 6, 2007 at 8:29 am
I have two "date" fields in a database, "ORIGREQDATE" and "NEWREQDATE" which have a datatype of CHAR and are formatted as YYYYMMDD.
The INSERT statement (which I cannot modify) inserts "Null" values as 00000000.
I am attempting to compare those dates against getdate(), and select data where the difference between the two dates is > 1.
My statement is Select (blah blah blah) where DATEDIFF(D, CONVERT(DATETIME, NEWREQDATE), GETDATE() ) > 1).
This works great, except when one of the fields = 00000000. In those instances, SQL throws the error "The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value."
I have experimented with CASE and HAVING, and various subqueries, but SQL always wants to do the DATEDIFF function regardless. No Joy.
I could construct a temporary table and have my front end talk to that table, but would prefer not to do so.
I think this is what I am looking for, logically: Look at NEWREQDATE. If that field is NOT Null or 00000000, select the record IF DATEDIFF(D, CONVERT(DATETIME, NEWREQDATE), GETDATE() ) > 1). If NEWREQDATE is NULL or 00000000, look at ORIGREQDATE and select the record if DATEDIFF(D, CONVERT(DATETIME, ORIGREQDATE), GETDATE() ) > 1).
Any help would be greatly appreciated. MB
February 6, 2007 at 8:48 am
Not tested, and I was tempted to put a different case statement around the NEWREQDATE in your existing logic, but without knowing your reqs, it might or might not be a good idea. This should do the trick either way:
WHERE
0 < CASE NEWREQDATE
WHEN
'00000000'
THEN
1 -- Or use 0 (zero) if you want those to fail to match the where criteria
ELSE
DATEDIFF(D, CONVERT(DATETIME, NEWREQDATE), GETDATE() )
END
If it still tries to do the implicit conversion, let me know whether '00000000' should pass or fail the WHERE clause and we'll do it inline, which should work.
February 6, 2007 at 9:08 am
David,
Thanks for the reply. Sorry if my answer is obtuse, but I'm more experienced at front-end programming...in the WHERE clause, if NEWREQDATE = 000000000 THEN do the DATEDIFF on ORIGREQDATE, ELSE do the DATEDIFF on NEWREQDATE. Let me know if you'd like to take this thread offline.
Thanks
Mike
February 6, 2007 at 9:17 am
Is this what you want?
WHERE 1 =
CASE
WHEN NULLIF(NEWREQDATE, '00000000') IS NULL AND NULLIF(ORIGREQDATE, '00000000') IS NULL
THEN 0
WHEN NULLIF(NEWREQDATE, '00000000') IS NULL
AND DATEDIFF(d, CAST(ORIGREQDATE AS datetime), GETDATE()) > 1
THEN 1
WHEN NULLIF(NEWREQDATE, '00000000') IS NOT NULL
AND DATEDIFF(d, CAST(NEWREQDATE AS datetime), GETDATE()) > 1
THEN 1
ELSE 0
END
February 6, 2007 at 9:40 am
Ken,
That seems to work. Now off to BooksOnline to figure out what you did.
Thanks
Mike
February 6, 2007 at 12:43 pm
I'm not Ken, but since we both used the same method, I'll see if I can explain it to you from a high level. First, WHERE doesn't allow things like: WHERE CASE blah blah blah END CASE, therefore we give it a literal on one side of the equal sign, a 1 in this case. Then, the goal is to return a 1 on the other side when we want the record returned, and something else (a zero here) when we don't want the record returned.
WHEN NULLIF(NEWREQDATE, '00000000') IS NULL AND NULLIF(ORIGREQDATE, '00000000') IS NULL
THEN 0
Here, Ken's saying that if both NEWREQDATE and ORIGREQDATE are null or '00000000', don't return this row. In other words, no date in either place, no row. Notice the "THEN 0", which doesn't match the 1 on the left hand side of the equal sign in the WHERE clause.
WHEN NULLIF(NEWREQDATE, '00000000') IS NULL
AND DATEDIFF(d, CAST(ORIGREQDATE AS datetime), GETDATE()) > 1
THEN 1
Here, he's saying that if NEWREQDATE is '00000000' or Null and ORIGREQDATE returns a difference greater than 1, return the row. Hence, the "THEN 1", which does match the 1 on the left hand side of the equal sign.
WHEN NULLIF(NEWREQDATE, '00000000') IS NOT NULL
AND DATEDIFF(d, CAST(NEWREQDATE AS datetime), GETDATE()) > 1
THEN 1
Here, NEWREQDATE is neither '00000000' nor is it Null, therefore check the diff using NEWREQDATE, and if it's greater than 1, return the rows. Hence the "THEN 1" again.
ELSE 0
Finally, he's saying that if none of the other conditions were met, return a 0, which doesn't match, therefore no rows. This is useful even if you can't imagine a circumstance in which the other conditions won't be met, as as soon as you think you've covered all of the bases is when you'll find out that you're mistaken. I sometimes even put a print statement in that final else, to let me know that the other conditions weren't met. Great for testing.
February 6, 2007 at 4:17 pm
Another victim of NULL replacement.
You need just restore NULL where it suppose to be:
where DATEDIFF(D, CONVERT(DATETIME, NULLIF(NEWREQDATE, '00000000'), GETDATE() ) > 1
_____________
Code for TallyGenerator
February 6, 2007 at 9:26 pm
Since you have the dates stored in a character column, it might be faster to do string comparisons, instead of casting two columns to datetime to do the compares, especially if you have an index on them. Even if there are no indexes, it will avoid casting each column to a date.
This query will return data where the date is before yesterday.
select * from MyTable where ( NEWREQDATE between '17530101' and convert(varchar(30),getdate()-2,112) ) or ( ( NEWREQDATE is null or NEWREQDATE = '00000000' ) and ( ORIGREQDATE between '17530101' and convert(varchar(30),getdate()-2,112) )
Of course you know that it's a cardinal sin to store your dates in a character string, so I won't dwell on that. Go forth, and sin not more.
February 7, 2007 at 7:39 am
You can use NULLIF to change the '00000000' values back to NULL, but then you have to use ISNULL to replace the result with something > 1 if you want to select them.
WHERE
ISNULL(DATEDIFF(d, CONVERT(DATETIME, NULLIF(ORIGREQDATE, '00000000')), GETDATE()), 99999) > 1
OR ISNULL(DATEDIFF(d, CONVERT(DATETIME, NULLIF(NEWREQDATE, '00000000')), GETDATE()), 99999) > 1
February 7, 2007 at 8:32 am
Michael (and all)
Thanks to everyone for the replies. What a great learning (and teaching) tool web forums can be.
The great comedian/pianist Victor Borge said once, "It's YOUR language, I'm just trying to use it..."
I hold no claim to the design of this database. It's an old HP MPE/ix database that was ported over almost 'As Is' to SQL Server. Fixed-length fields, packed fields, decimals stored as character fields, oh my...and since we're using a boxed app as the main front end, I cannot change any of the underlying structure. I am writing VB.NET front ends to handle things that the boxed app does not or cannot.
Thanks again.
Mike
February 12, 2007 at 2:53 am
... and another illustration of why dates should be stored as dates, not character strings !!!!
February 13, 2007 at 2:36 am
Hi,
Date is a varchar field and it can contain some invalid dates also beside "0000000" So, You should Check for all invalid dates instead of checking "0000000".
Try this below mentioned Query and implement it as per your requirement :
Select Datediff(dd,[date],Getdate()) From
(
Select Case When Isdate([Date[)=0 then Null
Else [Date] End [Date] From
Table_Name
) a
Thanks & Regards,
Amit Gupta
/* Remove all physical & sychological barriers */
Viewing 12 posts - 1 through 11 (of 11 total)
You must be logged in to reply to this topic. Login to reply