In my SSIS package, I have to converting values from DateTime to a corresponding INTEGER value. The following sample has been provided.
Any ideas as to how I can convert these?
DATETIME INT
--------- ----
1/1/2009 39814
2/1/2009 39845
3/1/2009 39873
4/1/2009 39904
5/1/2009 39934
6/1/2009 39965
7/1/2009 39995
8/1/2009 40026
9/1/2009 40057
10/1/2009 40087
11/1/2009 40118
12/1/2009 40148
1/1/2010 40179
2/1/2010 40210
3/1/2010 40238
4/1/2010 40269
5/1/2010 40299
6/1/2010 40330
EDIT: Casting to a float/int no longer works in recent versions of SQL Server. Use the following instead:
select datediff(day, '1899-12-30T00:00:00', my_date_field)
from mytable
Note the string date should be in an unambiguous date format so that it isn't affected by your server's regional settings.
In older versions of SQL Server, you can convert from a DateTime to an Integer by casting to a float, then to an int:
select cast(cast(my_date_field as float) as int)
from mytable
(NB: You can't cast straight to an int, as MSSQL rounds the value up if you're past mid day!)
If there's an offset in your data, you can obviously add or subtract this from the result
You can convert in the other direction, by casting straight back:
select cast(my_integer_date as datetime)
from mytable
select DATEDIFF(dd, '12/30/1899', mydatefield)
Or, once it's already in SSIS, you could create a derived column (as part of some data flow task) with:
(DT_I8)FLOOR((DT_R8)systemDateTime)
But you'd have to test to doublecheck.
Related
I have a column of number data type in snowflake that stores values like 20220401, now I need to convert it into date format. Could someone please help
You can use to_date, but it works on char datatype, so first need to convert your column to char/string.
with data_cte(col1) as
(select 20220401::number)
select to_date(col1::string,'yyyymmdd') from data_cte
select to_date('02/14/2014', 'MM/DD/YYYY');
create table number_to_date(numbers integer);
insert into number_to_date values (20220401);
select to_date(to_char(numbers),'YYYYMMDD') from number_to_date;
More details: https://docs.snowflake.com/en/sql-reference/functions/to_date.html#examples
Yet more way's of seeing/saying the same thing:
to_date allows you to define format string
select column1 as raw_str,
to_date(column1, 'yyyymmdd') as as_date
from values
('19900101'),
('20220511');
gives:
RAW_STR
AS_DATE
19900101
1990-01-01
20220511
2022-05-11
if you have string that sometimes are not following the format pattern you might want to use try_to_date as this will not generate an error:
select column1 as raw_str,
try_to_date(column1, 'yyyymmdd') as as_date
from values
('19900101'),
('not a date'),
('20220511');
RAW_STR
AS_DATE
19900101
1990-01-01
not a date
null
20220511
2022-05-11
But given you said "number input"
select column1 as raw_number,
to_date(column1::text, 'yyyymmdd') as as_date
from values
(19900101),
(20220511);
now we have numbers, but to_date wants text, so we cast it to text, so the parser can be used.
giving:
RAW_NUMBER
AS_DATE
19,900,101
1990-01-01
20,220,511
2022-05-11
Now if you use TO_TIMESTAMP which accepts the same format string, the naked number by itself it will think you mean epoch seconds, and give you wacky tiny number, like:
select column1 as raw_number,
to_timestamp(column1) as as_timestamp
from values
(19900101),
(20220511);
RAW_NUMBER
AS_TIMESTAMP
19,900,101
1970-08-19 07:48:21.000
20,220,511
1970-08-23 00:48:31.000
which is all to say, cast it to string via ::text or the likes, and specify your format, so that you can handle yyyymmdd or yyyyddmm or how every your data is.
Table is having the column as ret_period and contains varchar datatype. I'm trying to write the query for converting the datatype of column from varchar to date datatype .but it is throwing an error as Conversion failed when converting date and/or time from character string.
Can any one please let me know how to resolve this issue!
below is the sample data of column.
ret_period
012018
012019
012020
You could transform the string to a format that can be converted/casted to a DATE.
select *
, TRY_CAST(CONCAT(RIGHT(ret_period, 4),'-',LEFT(ret_period, 2),'-01') AS DATE) AS ret_date
from (values
('012018'),
('012019'),
('012020')
) q(ret_period)
Note however, that the yyyyMMDD format should be a safer than yyyy-MM-DD, since it doesn't depend on the language when casting it to a DATETIME.
Or use the DATEFROMPARTS function
select *
, DATEFROMPARTS(RIGHT(ret_period, 4), LEFT(ret_period, 2), 1) AS ret_date
from (values
('012018'),
('012019'),
('012020')
) q(ret_period)
ret_period
ret_date
012018
2018-01-01
012019
2019-01-01
012020
2020-01-01
I am trying to clean my data prior to loading into PowerBI to create the visuals. I have created my query as:
CREATE VIEW Project2 AS (
Select
p.playerID as ID1,
p.birthYear,
p.birthMonth,
p.birthDay,
p.birthCity,
p.deathYear,
p.nameFirst,
p.nameLast,
p.nameGiven,
p.weight,
p.bats,
p.throws,
p.finalGame,
b.*
from dbo.People as p
LEFT JOIN dbo.Batting as b
ON p.playerID=b.playerID
and b.G >= 50
WHERE (p.finalGame is null or p.finalGame >= 2018));
This works great until attempting to load the view into PowerBI I get this error:
DataSource.Error: Microsoft SQL: Conversion failed when converting the varchar value '2015-08-23' to data type int.
Details:
DataSourceKind=SQL
DataSourcePath=laptop-o4rhi9q7;Baseball
Message=Conversion failed when converting the varchar value '2015-08-23' to data type int.
ErrorCode=-2146232060
Number=245
Class=16
I can't figure out where /how to utilize cast(p.finalGame as date) in correct syntax, any ideas?
You must use a proper date literal for this, which means it must be enclosed in quotes, and ideally use a non-ambiguous format
WHERE (p.finalGame is null or p.finalGame >= '20180101'));
If finalGame is actuall varchar you would need to convert it using an appropriate conversion type. For example
WHERE (p.finalGame is null or CONVERT(date, p.finalGame, 102) >= '20180101'));
That may not be the correct format number, the full list is here.
I urge you to change the column type to date in the first place.
If the data for p.finalGame = '2015-08-23', you'll need to cast that as a date in your WHERE clause.
CREATE VIEW Project2 AS (
Select
p.playerID as ID1,
p.birthYear,
p.birthMonth,
p.birthDay,
p.birthCity,
p.deathYear,
p.nameFirst,
p.nameLast,
p.nameGiven,
p.weight,
p.bats,
p.throws,
p.finalGame,
b.*
from dbo.People as p
LEFT JOIN dbo.Batting as b
ON p.playerID=b.playerID
and b.G >= 50
WHERE (p.finalGame is null or cast(p.finalGame as DATE) >= 2018));
Based on the error message, you date appears to be a string of the form 'yyyy-mm-dd', not a true date type or an integer year. I believe your fix is to quote your year. Either
WHERE (p.finalGame is null or p.finalGame >= '2018');
or
WHERE (p.finalGame is null or p.finalGame >= '2018-01-01');
If your year is a variable, convert it to a string with something like CONVERT(VARCHAR(10), #Year). (This assumes a 4 digit value.)
As already noted, a better approach (if you have the ability to change the schema) is to redefine finalGame as a true DATE or DATETIME type. Then you could compare p.finalGame >= '2018-01-01' or p.finalGame >= DATEFROMPARTS(#Year, 1, 1).
I'm new to the T-SQl world and this issue is puzzling me.
I'm running a query against a variable I have created which holds the date of the start of my financial year, which is 2014-04-01. The data I'm querying against holds the date as a date time field, so I have been using CAST AS DATE to remove the timestamp.
If I run this query in this fashion I receive 25 results:
select count(B.WorkOrderNumber) as AWOCount
from TSP1_Dev.AssetDataPortal.EllipseSiteList A left outer join
TSP1_Dev.AssetDataPortal.tblWorkOrdersActive B
on A.EquipmentLocation = B.EquipmentLocation
where
B.EquipmentLocation = 'BISHT'
and A.EquipmentClass = 'SW'
and right(rtrim(A.EquipmentDesc),4) = '(OU)'
and cast(B.CreationDate as Date) >= '2014-04-01';
However, on one occasion I forgot to cast the date, and when I did that I received 32 results:
select count(B.WorkOrderNumber) as AWOCount
from TSP1_Dev.AssetDataPortal.EllipseSiteList A left outer join
TSP1_Dev.AssetDataPortal.tblWorkOrdersActive B
on A.EquipmentLocation = B.EquipmentLocation
where
B.EquipmentLocation = 'BISHT'
and A.EquipmentClass = 'SW'
and right(rtrim(A.EquipmentDesc),4) = '(OU)'
and B.CreationDate >= '2014-04-01';
Can someone please tell me why? Apologies for my ignorance!
Neil
In the query you have string literals and from your comment I can only assume that it is Coldfusion that insert the string literal in your query. (I know nothing about Coldfusion but is there no way to use parameters instead?).
In SQL Server there is a setting for the order of date parts in strings. SET DATEFORMAT
What you see can be reproduced if you have the date format dmy.
The string literal 2014-04-01 is interpreted as yyyy-dd-mm when compared against a datetime. When the new data types date and datetime2 was added that behaviour was changed so string literal on the form yyyy-mm-dd will always be interpreted as just that regardless of set dateformat.
So when you cast to date the string literal is converted to the date 2014-04-01 but when you compare against a datetime the string literal is converted to 2014-01-04.
set dateformat dmy;
declare #T table(D datetime);
insert into #T(D) values
('20140101'),('20140201'),
('20140301'),('20140401'),
('20140501'),('20140601');
select count(*)
from #T
where D >= '2014-04-01';
select count(*)
from #T
where cast(D as date) >= '2014-04-01';
Result:
5
3
One way to avoid the problem for datetime is to use a string literal without dashes. 20140401 will be interpreted as yyyymmdd regardless of set dateformat.
in MySQL
select * from record where register_date like '2009-10-10%'
What is the syntax in SQL Server?
You could use the DATEPART() function
SELECT * FROM record
WHERE (DATEPART(yy, register_date) = 2009
AND DATEPART(mm, register_date) = 10
AND DATEPART(dd, register_date) = 10)
I find this way easy to read, as it ignores the time component, and you don't have to use the next day's date to restrict your selection. You can go to greater or lesser granularity by adding extra clauses, using the appropriate DatePart code, e.g.
AND DATEPART(hh, register_date) = 12)
to get records made between 12 and 1.
Consult the MSDN DATEPART docs for the full list of valid arguments.
There's no direct support for LIKE operator against DATETIME variables, but you can always cast the DATETIME to a VARCHAR:
SELECT (list of fields) FROM YourTable
WHERE CONVERT(VARCHAR(25), register_date, 126) LIKE '2009-10-10%'
Check the MSDN docs for a complete list of available "styles" in the CONVERT function.
Marc
If you do that, you are forcing it to do a string conversion. It would be better to build a start/end date range, and use:
declare #start datetime, #end datetime
select #start = '2009-10-10', #end = '2009-11-10'
select * from record where register_date >= #start
and register_date < #end
This will allow it to use the index (if there is one on register_date), rather than a table scan.
You can use CONVERT to get the date in text form. If you convert it to a varchar(10), you can use = instead of like:
select *
from record
where CONVERT(VARCHAR(10),register_date,120) = '2009-10-10'
Or you can use an upper and lower boundary date, with the added advantage that it could make use of an index:
select *
from record
where '2009-10-10' <= register_date
and register_date < '2009-10-11'
Unfortunately, It is not possible to compare datetime towards varchar using 'LIKE'
But the desired output is possible in another way.
select * from record where datediff(dd,[record].[register_date],'2009-10-10')=0
You can also use convert to make the date searchable using LIKE. For example,
select convert(VARCHAR(40),create_date,121) , * from sys.objects where convert(VARCHAR(40),create_date,121) LIKE '%17:34%'
Try this
SELECT top 10 * from record WHERE IsActive = 1
and CONVERT(VARCHAR, register_date, 120) LIKE '2020-01%'
I am a little late to this thread but in fact there is direct support for the like operator in MS SQL server.
As documented in LIKE help if the datatype is not a string it is attempted to convert it to a string. And as documented in cast\convert documentation:
default datetime conversion to string is type 0 (,100) which is mon dd
yyyy hh:miAM (or PM).
If you have a date like this in the DB:
2015-06-01 11:52:59.057
and you do queries like this:
select * from wws_invoice where invdate like 'Jun%'
select * from wws_invoice where invdate like 'Jun 1%'
select * from wws_invoice where invdate like 'Jun 1 %'
select * from wws_invoice where invdate like 'Jun 1 2015:%'
select * from wws_invoice where invdate like 'Jun ? 2015%'
...
select * from wws_invoice where invdate like 'Jun 1 2015 11:52AM'
you get that row.
However, this date format suggests that it is a DateTime2, then documentation says:
21 or 121 -- ODBC canonical (with milliseconds) default for time,
date, datetime2, and datetimeoffset. -- yyyy-mm-dd hh:mi:ss.mmm(24h)
That makes it easier and you can use:
select * from wws_invoice where invdate like '2015-06-01%'
and get the invoice record. Here is a demo code:
DECLARE #myDates TABLE (myDate DATETIME2);
INSERT INTO #myDates (myDate)
VALUES
('2015-06-01 11:52:59.057'),
('2015-06-01 11:52:59.054'),
('2015-06-01 13:52:59.057'),
('2015-06-01 14:52:59.057');
SELECT * FROM #myDates WHERE myDate LIKE '2015-06-01%';
SELECT * FROM #myDates WHERE myDate LIKE '2015-06-01 11%';
SELECT * FROM #myDates WHERE myDate LIKE '2015-06-01 11:52:59%';
SELECT * FROM #myDates WHERE myDate LIKE '2015-06-01 11:52:59.054%';
Doing datetime searches in SQL server without any conversion to string has always been problematic. Getting each date part is an overkill (which unlikely would use an index). Probably a better way when you don't use string conversion would be to use range checks. ie:
select * from record
where register_date >= '20091010' and register_date < '20091011';
The LIKE operator does not work with date parts like month or date but the DATEPART operator does.
Command to find out all accounts whose Open Date was on the 1st:
SELECT *
FROM Account
WHERE DATEPART(DAY, CAST(OpenDt AS DATE)) = 1`
*CASTING OpenDt because it's value is in DATETIME and not just DATE.
There is a very flaky coverage of the LIKE operator for dates in SQL Server. It only works using American date format. As an example you could try:
... WHERE register_date LIKE 'oct 10 2009%'
I've tested this in SQL Server 2005 and it works, but you'll really need to try different combinations. Odd things I have noticed are:
You only seem to get all or nothing for different sub fields within the date, for instance, if you search for 'apr 2%' you only get anything in the 20th's - it omits 2nd's.
Using a single underscore '_' to represent a single (wildcard) character does not wholly work, for instance, WHERE mydate LIKE 'oct _ 2010%' will not return all dates before the 10th - it returns nothing at all, in fact!
The format is rigid American: 'mmm dd yyyy hh:mm'
I have found it difficult to nail down a process for LIKEing seconds, so if anyone wants to take this a bit further, be my guest!
Hope this helps.
I solved my problem that way. Thank you for suggestions for improvements.
Example in C#.
string dd, mm, aa, trc, data;
dd = nData.Text.Substring(0, 2);
mm = nData.Text.Substring(3, 2);
aa = nData.Text.Substring(6, 4);
trc = "-";
data = aa + trc + mm + trc + dd;
"Select * From bdPedidos Where Data Like '%" + data + "%'";
I realise this an old question, but a lot of the answers here don't give a SARGable answer here, nor cover parmetrisation.
First off, you are far better off using >= and < logic. For the date you want, then that would look like this:
SELECT {Your Columns}
FROM dbo.record
WHERE register_date >= '20091010'
AND register_date < '20091011';
This'll include every time value on 2009-10-10, including the stroke of midnight on the day, and a nanosecond prior to 2009-10-11.
Often, however, you'll be parametrising your query, so instead what you can do is use DATEADD to add a day to the second clause:
DECLARE #DateParam date = '20091010';
SELECT {Your Columns}
FROM dbo.record
WHERE register_date >= #DateParam
AND register_date < DATEADD(DAY,1,#DateParam);
This maintains SARGability and means that any indexes on register_date can be used.