Unable to convert from Julian INT date to regular TSQL Datetime - tsql

Help me Stackoverflow, I'm close to going all "HULK SMASH" on my keyboard over this issue. I have researched carefully but I'm obviously not getting something right.
I am working with a Julian dates referenced from a proprietary tool (Platinum SQL?), though I'm working in SQL 2005. I can convert their "special" version of Julian into datetime when I run a select statement. Unfortunately it will not insert into a datetime column, I get the following error when I try:
The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value.
So I can't setup datetime criteria for running a report off of the Stored Procedure.
Original Value: 733416
Equivalent Calendar Value: 01-09-2009
Below is my code... I'm so close but I can't quite see what's wrong, I need my convert statement to actually convert the Julian value (733416) into a compatible TSQL DATETIME value.
SELECT
org_id,
CASE WHEN date_applied = 0 THEN '00-00-00'
ELSE convert(char(50),dateadd(day,date_applied-729960,convert(datetime, '07-25-99')),101)
END AS date_applied,
CASE WHEN date_posted = 0 THEN '00-00-00'
ELSE convert(char(50),dateadd(day,date_posted-729960,convert(datetime, '07-25-99')),101)
END AS date_posted
from general_vw

SELECT
org_id,
CASE WHEN date_applied = 0 OR date_applied < 639906 THEN convert(datetime, '1753-01-01')
ELSE dateadd(day,date_applied-729960,convert(datetime, '07-25-99'))
END AS date_applied,
CASE WHEN date_posted = 0 OR date_applied < 639906 THEN convert(datetime, '1753-01-01')
ELSE dateadd(day,date_posted-729960,convert(datetime, '07-25-99'))
END AS date_posted
from general_vw
You're casting to char but want a datetime so that's one easy fix.
You were also using '00-00-00' as your minimum date, but the minimum TSQL date is '1753-01-01'. Alternatively you could use something like ('1900-01-01') but that would need a change to the "less than" date_applied comparer.
I've added a "less than" date_applied comparer too. I calculated this as "SELECT 729960 + datediff(day,convert(datetime, '07-25-99'), convert(datetime,'1753-01-01'))". Any number less than this would cause a date underflow.

Related

Add to DATE hour - TSQL

I have a column type time(7).
What i want is to add in time column to date.
i manage to get the only date using GETDATE() function but i fail to add the time part next to date.
Query:
SELECT [Compay]
,[Time]
,CAST(GETDATE() AS DATE) AS Today
,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) AS Today_AS_Nvarchar
,CAST([Time] AS NVARCHAR) AS Time_AS_Nvarchar
,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) + ' ' + CAST([Time] AS NVARCHAR) AS Today_Time_AS_Nvarchar
,CONVERT(datetime,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) + ' ' + CAST([Time] AS NVARCHAR),103)
FROM [Testing_Env].[dbo].[Com_CD_Test]
Error:
Conversion failed when converting date and/or time from character string.
The error arise on CONVERT(datetime,CAST(CAST(GETDATE() AS DATE) AS NVARCHAR) + ' ' + CAST([Time] AS NVARCHAR),103)
is there any easier/orthodox way to achieve it?
You can't add the new date and time data types together like you can the old data types; personally I think this is also better as it stop people treating dates and times like a numerical value.
Assuming you have a date column and a time column you have a few of options. The first is to CAST/CONVERT both to a datetime and then "add" them together. Because the "old" data types work more like numerical values this works, however, you will lose accuracy of your time value if it has a precision of 3 or higher (as datetime is only accurate to 1/300 seconds):
DECLARE #TimeValue time(7) = '17:52:12.1234567',
#DateValue date = '20211016';
SELECT CONVERT(datetime, #DateValue) + CONVERT(datetime, #TimeValue);
If loosing accuracy isn't an option, then you could to use conversion on the date value and use DATEDIFF and DATEADD. For a time(7) you'll want to be using nanoseconds (as microseconds isn't accurate enough). Unfortunately this poses another problem; DATEADD can't handle bigint values (still) and there is no DATEADD_BIG (like there is DATEDIFF_BIG), so this becomes overly complex. You need to first get the difference in milliseconds, and then add the remainder in nanoseconds to still be accurate to 1/1000000 of a second:
DECLARE #TimeValue time(7) = '17:52:12.1234567',
#DateValue date = '20211016';
SELECT DATEADD(NANOSECOND,DATEDIFF_BIG(NANOSECOND,'00:00:00', #TimeValue) % 1000000,DATEADD(MILLISECOND, DATEDIFF_BIG(MILLISECOND,'00:00:00', #TimeValue), CONVERT(datetime2(7),#DateValue)));
Finally, yes, you can convert to values to strings, and then to a datetime2 value; this is probably the easiest methiod. You just need to ensure you use style codes:
DECLARE #TimeValue time(7) = '17:52:12.1234567',
#DateValue date = '20211016';
SELECT CONVERT(datetime2(7),CONVERT(varchar(10), #DateValue, 23) + 'T' + CONVERT(varchar(17), #TimeValue, 114),126);

MySQL query show the result out of range

I have the following mysqli query in my search.php file with ajax.
SELECT demand2.* FROM demand2
WHERE ddate >= '$dto' AND ddate >= '$dfrom' AND !(mach='--' OR mach='-' OR mach='' OR mach='----' OR mach='-----' OR mach='---');
field ddate is datatype of varchar2
as I entered Date From 01-01-2019 and Date To 30-01-2019, it shows the result with previous date like 29-12-2019.
So I can't find the solution to get result within specified range. Please Help.
Just as rypskar said, your type of field should be date.
If you don't want to change the datatype of the fiels, then you have to convert the string to date with STR_TO_DATE(ddate, '%d-%m-%Y'). But this is not recommended, as it will cause performance degradation on larger tables.
So your query would be like that (not tested!):
SELECT demand2.* FROM demand2
WHERE STR_TO_DATE(ddate, '%d-%m-%Y') >= STR_TO_DATE('$dto', '%d-%m-%Y') AND STR_TO_DATE(ddate, '%d-%m-%Y') >= STR_TO_DATE('$dfrom', '%d-%m-%Y') AND !(mach='--' OR mach='-' OR mach='' OR mach='----' OR mach='-----' OR mach='---');
If you want to keep the varchar type of field and not make any runtime conversions, then you have to change the format to Y-m-d, so the comparison with character set will work the same as a date comparison.
Right now, you are getting the result of 29-12-2019 because 29 is between 1 and 30.

Convert packed DB2 iseries value to YYYY-MM-DD

I'm trying to select records from a DB2 Iseries system where the date field is greater than the first of this year.
However, the date fields I'm selecting from are actually PACKED fields, not true dates.
I'm trying to convert them to YYYY-MM-DD format and get everything greater than '2018-01-01' but no matter what I try it says it's invalid.
Currently trying this:
SELECT *
FROM table1
WHERE val = 145
AND to_date(char(dateShp), 'YYYY-MM-DD') >= '2018-01-01';
it says expression not valid using format string specified.
Any ideas?
char(dateshp) is going to return a string like '20180319'
So your format string should not include the dashes.. 'YYYYMMDD'
example:
select to_date(char(20180101), 'YYYYMMDD')
from sysibm.sysdummy1;
So your code should be
SELECT *
FROM table1
WHERE val = 145
AND to_date(char(dateShp), 'YYYYMMDD') >= '2018-01-01';
Charles gave you a solution that converts the Packed date to a date field, and if you are comparing to another date field, this is a good solution. But if you are comparing to a constant value or another numeric field, you could just use something like this:
select *
from table1
where val = 145
and dateShp >= 20180101;

TSQL DateTime Comparison

What I am trying to do is get a result from sql where the dates are in a certain range but its not working correctly, here is my query.
DECLARE #CurrDate DATETIME
SET #CurrDate = GETDATE()
SELECT dbo.ProductDetails.PartnerID
,dbo.ProductDetails.ProductID
,dbo.Products.ProductName
,StartDate
,EndDate
FROM dbo.ProductDetails
INNER JOIN dbo.Products
ON dbo.ProductDetails.ProductID = dbo.Products.ProductID
WHERE CONVERT(VARCHAR(10),StartDate,111) <= #CurrDate
AND CONVERT(VARCHAR(10),EndDate, 111) >= #CurrDate
but when the Enddate = #CurrDate the row does not show, but if i make that date just one day higher it gets displayed. Am i doing anything wrong? Any advice will do, thanks.
GetDate() returns date and time, while your conversion to varchar strips away the time part (I'm suspecting that's all it's actually supposed to do). So you would need to do the same conversion for #CurrDate.
If what you want is to simply consider the date only (ignoring the time part), you could use DATEDIFF instead of converting to varchar (see here); example:
DECLARE #CurrDate DATETIME
SET #CurrDate = GETDATE()
SELECT dbo.ProductDetails.PartnerID, dbo.ProductDetails.ProductID,
dbo.Products.ProductName , StartDate, EndDate
FROM dbo.ProductDetails INNER JOIN
dbo.Products ON dbo.ProductDetails.ProductID = dbo.Products.ProductID
-- where StartDate is on the same day or before CurrDate:
WHERE DATEDIFF(day, StartDate, #CurrDate) >= 0 AND
-- and where EndDate is on the same day or after CurrDate:
DATEDIFF(day, EndDate, #CurrDate) <= 0
If you want only DATE comparison, without time use the
cast(CONVERT(varchar, StartDate, 112) as datetime)
I am quite sure that the comparison takes into account the time as well as the date, in which case if the dates are the same but the current time is greater than the time being compared to you won't get that row as a result.
So, what you need to do is just extract the date part and compare those.
GETDATE() gives you date and time
if yours column have only date
then
CONVERT(VARCHAR(10),StartDate,111) <= #CurrDate
can give you unexpected result
remember
19.12.2011 14:41 > 19.12.2011 00:00
If you are using SQL 2008 or later, and wanting to compare only the date, not the time, you can also do:
Cast(StartDate as Date)
(This avoids having to convert to a string.)

SQL SERVER passing getdate() or string date not working correctly

CREATE PROCEDURE sp_ME
#ID int,
#ThisDate datetime = null
AS
SET NOCOUNT ON
IF #ThisDate IS NULL
BEGIN
SET #ThisDate = CURRENT_TIMESTAMP
END
DECLARE #intErrorCode int,
#QBegin datetime,
#QEnd datetime
SELECT #intErrorCode = ##ERROR
IF #ThisDate BETWEEN '01/01/' + CONVERT(VARCHAR(4), YEAR(#ThisDate))
AND '03/31/' + CONVERT(VARCHAR(4), YEAR(#ThisDate))
BEGIN
Select #QBegin = DATEADD(s,0,CAST ('10/01/' AS varchar(6) ) +
CONVERT(VARCHAR(4),DATEPART (year,#ThisDate)-1))
Select #QEnd = DATEADD(s,-1,DATEADD(mm, DATEDIFF(m,0,#QBegin)+3,0))
SELECT * FROM QUERY
WHERE MEID = #ID
AND mydate >= #QBegin
AND mydate <= #QEnd)
END
SELECT #intErrorCode = ##ERROR
IF (#intErrorCode <> 0) GOTO ErrHandler
ErrHandler:
RETURN #intErrorCode
GO
It returns a dataset when you leave it blank and it assumes and fills in the date, however when you plug in a date it just states "The command completed successfully."
Any help would be more than appreciated.
At a guess, you need to query the previous quarter's results, which would just be this query:
SELECT * FROM QUERY
WHERE MEID = #ID
AND mydate >= DATEADD(quarter,DATEDIFF(quarter,'20010101',#ThisDate),'20001001'),
AND mydate < DATEADD(quarter,DATEDIFF(quarter,'20010101',#ThisDate),'20010101'))
And get rid of that big if condition, etc.
You could also get rid of the first if, if you put COALESCE(#ThisDate,CURRENT_TIMESTAMP) in the above, where I currently have #ThisDate.
I use the DATEADD(quarter,DATEDIFF(quarter,'20010101',#ThisDate),'20001001') pattern for a lot of datetime manipulation. It let's you achieve a lot in a few operations. In this case, it's the difference between the two dates ('20010101','20001001') which is giving us the previous quarter.
You'll frequently encounter the DATEADD/DATEDIFF pattern in questions involving removing the time portion from a datetime value. The canonical version of this is DATEADD(day,DATEDIFF(day,0,#Date),0). But the pattern can be generally extended to work with any of the datetime components. If you choose month rather than day, you'll get midnight at the start of the first of the month (of the day you've supplied)
Where it gets tricky is when you use dates (instead of 0), and especially if you don't use the same date for both calculations. This allows you to apply an additional offset that seems almost "free" - you're already using this construct to remove the time component, the fact that you can compute e.g. the last date in a quarter/month/etc is a bonus.