Use part of VARCHAR column as date in where clause - sql

I have a table where the varchar column CREATED_BY has the data in the format
USER - dd/MM/yyyy hh:mm.
I'm trying to do data migration and need to get records where the created date is greater than a certain date, but the format of the column makes this difficult, so
SELECT * FROM TABLE_NAME WHERE -- last part of CREATED_BY > SOMEDATE

Well, since the dd/MM/yyyy hh:mm format has a fixed length, you can use the RIGHT function to extract the data part from your string:
SELECT *
FROM TABLE_NAME
WHERE CONVERT(datetime, RIGHT(CREATED_BY, 16), 103) > somedate

You need to extract the date from the string:
WHERE cast(reverse ( substring ( reverse ( #string ) , 1 , 16 ) ) as datetime) > somedate

Related

CONVERT Date INT to DATE in SQL

How can I convert a date integer to a date type? (20200531 into 5/31/2020)
My current table has a datadate formatted as YYYYMMDD (20200531, 20200430, etc.)
The Datatype for the datadate is an int according the Toad Data Point software I'm using. I believe it's using ORACLE sql database.
As a result, when querying this data, I have to type in the where clause as below..
where datadate = '20200531'
My goal is to convert this integer datadate into a date format (5/31/2020) so I can apply the datadate to the where clause.
like..
WHERE datadate = dateadd(DD, -1, CAST(getdate() as date))
(Read below for my answer for if it's an int column)
Assuming it's a textual string:
Assuming that datadate is a string (character, text, etc) column and not a date/datetime/datetime2/datetimeoffset column, then use the CONVERT function with style: 23. The 23 value corresponds to ISO 8601 because the values are in yyyy-MM-dd-order, even though they're missing dashes.
This page has a reference of style numbers: https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver15
SELECT
*
FROM
(
SELECT
myTable.*
CONVERT( date, datadate, 23 ) AS valueAsDate
FROM
myTable
) AS q
WHERE
q.valueAsDate = DATEADD( dd, -1, GETDATE() )
Assuming it's an actual int column:
The quick-and-dirty way is to convert the int to varchar and then use the same code as above as if it were a textual field - but don't do this because it's slow:
SELECT
*
FROM
(
SELECT
myTable.*,
CONVERT( char(8), datadate ) AS valueAsChar,
CONVERT( date, CONVERT( char(8), datadate ), 23 ) AS valueAsDate
FROM
myTable
) AS q
WHERE
q.valueAsDate = DATEADD( dd, -1, GETDATE() )
Assuming it's an actual int column (better answer):
We'll need to use DATEFROMPARTS and extract each component using Base-10 arithmetic (fun)!
If we have an integer representing a formatted date (the horror) such as 20200531 then:
We can get the day by performing MOD 31 (e.g. 19950707 MOD 31 == 7)
We can get the month by first dividing by 100 to remove the day part, and then MOD 12: (e.g. 20200531 / 100 == 202005, 202005 MOD 12 == 5)
We can get the year by dividing by 10,000, (e.g. 20200531 / 10000 == 2020).
Btw:
SQL Server uses % for the Modulo operator instead of MOD.
Integer division causes truncation rather than producing decimal or floating-point values (e.g. 5 / 2 == 2 and not 2.5).
Like so:
SELECT
q2.*
FROM
(
SELECT
q.*,
DATEFROMPARTS( q.[Year], q.MonthOfYear, q.DayOfMonth ) AS valueAsDate
FROM
(
SELECT
myTable.*,
( datadate % 31 ) AS DayOfMonth,
( ( datadate / 100 ) % 12 ) AS MonthOfYear,
( datadate / 10000 ) AS [Year]
FROM
myTable
) AS q
) AS q2
WHERE
q2.valueAsDate = DATEADD( dd, -1, GETDATE() )
Obviously, having two nested subqueries is a pain to work with (SQL has terrible ergonomics, I don't understand how or why SQL doesn't allow expressions in a SELECT clause to be used by other expressions in the same query - it's really bad ergonomics...) - but we can convert this to a scalar UDF (and SQL Server will inline scalar UDFs so there's no performance impact).
This function has a TRY/CATCH block in it because of the possibility that you process an invalid value like 20209900 (which isn't a real date as there isn't a 99th month with a 0th day in 2020). In this event the function returns NULL.
CREATE FUNCTION dbo.convertHorribleIntegerDate( #value int ) RETURNS date AS
BEGIN
DECLARE #dayOfMonth int = #value % 31;
DECLARE #monthOfYear int = ( #value / 100 ) % 100;
DECLARE #year int = #value / 10000;
BEGIN TRY
RETURN DATEFROMPARTS( #dayOfMonth, #monthOfYear, #year );
END TRY;
BEGIN CATCH
RETURN NULL;
END CATCH;
END
Which we can use in a query like so:
SELECT
myTable.*,
dbo.convertHorribleIntegerDate( datadate ) AS valueAsDate
FROM
myTable
As SELECT cannot share expression results with other expressions in the same query, you'll still need to use an outer query to work with valueAsDate (or repeat the dbo.convertHorribleIntegerDate function call):
SELECT
*
FROM
(
SELECT
myTable.*,
dbo.convertHorribleIntegerDate( datadate ) AS valueAsDate
FROM
myTable
) AS q
WHERE
q.valueAsDate = DATEADD( dd, -1, GETDATE() )
This answers assumes that you are running Oracle, as suggested in your question.
How can I convert a date integer to a date type? (20200531 into 5/31/2020)
In Oracle, you use to_date() to convert a string to a number. If you are giving it a number, it implicitly converts it to a string before converting it. So in both cases, you would do:
to_date(datadate, 'yyyymmdd')
My goal is to convert this integer datadate into a date format (5/31/2020) so I can apply the datadate to the where clause.
Generally, you want to avoid applying a function on a column in a where predicate: it is not efficient, because the database needs to apply the function on the entire column before it is able to filter. If you want to filter on dateadd as of yesterday, then I would recommend computing yesterday's date and putting it in the same format as the column that is filtered, so you can do a direct match against the existing column values.
If your column is a string:
where datadatea = to_char(sysdate - 1, 'yyyymmdd')
If it's a number:
where datadatea = to_number(to_char(sysdate - 1, 'yyyymmdd'))

Convert Decimal or Varchar into Date

I have 2 fields.
Birth= Datatype Decimal(12,4) & Date = Datatype Date
Birth Date
19650101 2015-07-09
how do i get a result that looks like this
i want the result to be like this
Birth Date
1965-01-01 2015-07-09
where the Birth is a Date datatype and not a decimal (12,4)
To convert the number 19650101 to a date use
CONVERT(DATETIME, CAST(Birth AS VARCHAR(8)), 112)
To get the number of years (to one decimal) you could do:
ROUND(
DATEDIFF(day,
CONVERT(DATETIME, CAST(Birth AS VARCHAR(8)), 112),
[Date])/365.25
,1)
Which won't be exact but should be close enough to tenths of a year.
You can use this:
-- Create demo data
CREATE TABLE #dates(birth int, date date)
INSERT INTO #dates(birth,date)
VALUES(19650101,N'2015-07-09')
-- Your work
SELECT CONVERT(date,CONVERT(nvarchar(max),birth),112) as birth, date,
DATEDIFF(year,
CONVERT(date,CONVERT(nvarchar(max),birth),112),
date
) as years
FROM #dates
-- Cleanup
DROP TABLE #dates
This depends on the exact format you provides (19650101).
Here is one way to do this conversion.
cast(cast(FLOOR(birth) as CHAR(8)) as DATE)
I think you don't need to round. Just convert your decimal value and put "-" like below : )
select left(birth,4) +'-' +
substring(convert(nvarchar,birth),5,2)+'-'+
substring(convert(nvarchar,birth),7,2)

SQL Output to get only last 7 days output while using convert on date

I am using the below SQL Query to get the data from a table for the last 7 days.
SELECT *
FROM emp
WHERE date >= (SELECT CONVERT (VARCHAR(10), Getdate() - 6, 101))
AND date <= (SELECT CONVERT (VARCHAR(10), Getdate(), 101))
ORDER BY date
The data in the table is also holding the last year data.
Problem is I am getting the output with Date column as
10/11/2013
10/12/2012
10/12/2013
10/13/2012
10/13/2013
10/14/2012
10/14/2013
10/15/2012
10/15/2013
10/16/2012
10/16/2013
10/17/2012
10/17/2013
I don't want the output of 2012 year. Please suggest on how to change the query to get the data for the last 7 days of this year.
Instead of converting a date to a varchar and comparing a varchar against a varchar. Convert the varchar to a datetime and then compare that way.
SELECT
*
FROM
emp
WHERE
convert(datetime, date, 101) BETWEEN (Getdate() - 6) AND Getdate()
ORDER BY
date
Why convert to varchar when processing dates? Try this instead:
DECLARE #Now DATETIME = GETDATE();
DECLARE #7DaysAgo DATETIME = DATEADD(day,-7,#Now);
SELECT *
FROM emp
WHERE date BETWEEN #7DaysAgo AND #Now
ORDER BY date
Use this, simply.
Select columnname
from tablename
WHERE datecolumn> dateadd(day,-7,GETDATE())

converting date from varchar to date

I am trying to change the date format of a column, the column is set as varchar column name date time. The problem is that i cannot actually change the data type because the data is automatically inputted by a PLC on the automation side. I need the date in a date or numeric value because when i run my queries i need to give the system a date range. I am trying to use substrings to work around this issue but am getting an error saying that the data type is out of range. here is the syntax of my query.
select cast(
(substring(datetime, 1, 4) + '-' +
SUBSTRING(DateTime, 5, 2) + '-' +
SUBSTRING(DateTime, 7, 2) + ' ' + '00:00:00.000') as dateTime) as "Date"
, ID1
, ID2
, diameter
, WeightTheoretical
, WeightActual
, StockType
from table1
where datetime is not null
and datetime <> ''
and datetime <> '0'
order by "Date", ID1;
Edit- the date format is as such 20120622:00:00:00:000
Assuming your date is with the format yyyymmdd, you can convert the varchar to datetime like this:
select convert(datetime, columname, 112)
It looks from your SQL that your date string is of the format YYYYMMDD
This should convert fine using either the CAST or CONVERT functions:
eg
SELECT CONVERT(datetime,'20120601')
SELECT CAST('20120601' as datetime)
both return the expected value as a datetime.
EDIT: Based on the supplied format you specified, I'd use the SubString to chop the supplied data down a bit:
eg
SELECT CONVERT(datetime,SUBSTRING('20120601',1,8))
Based on the format of your data in the table (20120622:00:00:00:000) you can do the following:
declare #date varchar(50)
set #date = '20120622:00:00:00:000'
select cast(left(#date, 8) as datetime)
or
select convert(datetime, left(#date, 8))
results:
2012-06-22 00:00:00.000

SQL: Error when trying to filter out all dates older than the current date

I'm using SQL SERVER 2008.
I have a table that stores dates in datetime format (i.e.2012-01-21 15:00:00.000)
I'm trying to filter out all the dates older than "today". So I was attempting to do so by using the query below.
SELECT Date
FROM MyTable
WHERE Date >= GETDATE()
When I run that though, I get the following error.
Conversion failed when converting date and/or time from character string.
Is there something I'm doing wrong? Thanks for the help and let me know if I need to provide more information!
More Information:
[Date] is of type DateTime in MyTable.
I also have a View that simply selects [Date] and does no manipulation
I'm accessing [Date] via the View
It looks like your column is not a DATETIME data type after all. It is probably VARCHAR or similar. If you provide the DDL for the creation of the table, that would allow a more specific answer.
You don't say what locale your in as this will matter. The most likely possibility is that your DATE column isn't a DATETIME. You don't say what locale your in, but (as an example) US and UK datetime formats are treated differently when in reverse format.
UK sees the date as yyyy-dd-mm hh:mm:ss.fff
US sees the date as yyyy-mm-dd hh:mm:ss.fff
For example, this throws an error:
SET LANGUAGE british
GO
SELECT CAST ('1999-01-21 10:11:12.345' AS DATETIME)
GO
However if you change the locale to us_english, it will parse correctly.
If you want to gurantee it's always going to be parsed as yyyy-mm-dd, then you need to be strict and use the full ISO spec by specifying Z between the date and time, e.g.,: 1999-01-21Z10:11:12.345 will parse in the same way in both locales.
Ultimately, you want to change the Date column to a datatype of DATETIME, but you may need to temporarialy change your locale to be able to do this sucessfully; i.e.:
SET LANGUAGE us_english
GO
ALTER TABLE [...]
GO
SET LANGUAGE british
GO
Yet another fun 'gotcha' to watch out for when manipulating date/time data.
Sidenote: no I don't know why the Microsoft think us over in Blighty see the date as yyyy-dd-mm ... I've never encountered this format. Could be inherited from European formats?
First of all you should change this to:
SELECT [Date]
FROM MyTable
WHERE [Date] <= GETDATE()
That type of Column is [Date]????
If your date column is VARCHAR/NVARCHAR you need to convert that value to DATETIME. From your example, the right format should be:
SELECT [Date]
FROM MyTable
WHERE CONVERT(DATETIME,[Date],121) >= GETDATE()
SQL will implicitly convert a varchar to a datatime if you are comparing it to a datetime. The issue you're getting is that there is a record in your table that is not in a datetime format.
GOOD EXAMPLE:
SELECT *
INTO #Temp
FROM
(
SELECT '2010-01-21 15:00:00.000' [Date] UNION
SELECT '2012-01-21 05:30:00.000' [Date] UNION
SELECT '2015-01-21 07:45:00.000' [Date] UNION
SELECT '2020-01-21 11:20:00.000' [Date]
) x
SELECT *
FROM #Temp
WHERE [Date] > GETDATE()
DROP TABLE #Temp
BROKEN EXAMPLE:
SELECT *
INTO #Temp
FROM
(
SELECT '2010-01-21 15:00:00.000' [Date] UNION
SELECT '2012-01-21 05:30:00.000' [Date] UNION
SELECT '2015-01-21 07:45:00.000' [Date] UNION
SELECT 'a2020-01-21 11:20:00.000' [Date]
) x
SELECT *
FROM #Temp
WHERE [Date] > GETDATE()
DROP TABLE #Temp
The 'a' in the last record of the broken example will cause the error your getting.
WORK AROUND
SELECT *
INTO #Temp
FROM
(
SELECT '2010-01-21 15:00:00.000' [Date] UNION
SELECT '2012-01-21 05:30:00.000' [Date] UNION
SELECT '2015-01-21 07:45:00.000' [Date] UNION
SELECT 'a2020-01-21 11:20:00.000' [Date]
) x
SELECT *
FROM
(
SELECT CASE WHEN ISDATE([Date]) = 1 THEN [Date] ELSE '' END [Date]
FROM #Temp
) x
WHERE [Date] > GETDATE()
DROP TABLE #Temp
BETTER OPTION
SELECT *
INTO #Temp
FROM
(
SELECT '2010-01-21 15:00:00.000' [Date] UNION
SELECT '2012-01-21 05:30:00.000' [Date] UNION
SELECT '2015-01-21 07:45:00.000' [Date] UNION
SELECT 'a2020-01-21 11:20:00.000' [Date]
) x
SELECT *
FROM #Temp
WHERE CASE WHEN ISDATE([Date]) = 1 THEN [Date] ELSE '' END > GETDATE()
DROP TABLE #Temp