regular expression not working on the datetime column - sql

The date in my table looks like 2010-06-16 00:00:00.000
When I use the below regular expression, no rows get selected.
select mydate from mytable where mydate like '2010%'
However, when I use this one, rows do get selected correctly.
select mydate from mytable where mydate like '%2010%'
So, I thought that probably leading white spaces are getting added. To take those into account, I used the below query. But this doesn't work either.
select mydate from mytable where LTRIM(RTRIM(mydate)) like '2010%'
Since the first one works, it means, that there is something before the 2010? What else apart from white spaces, could it be? I tried pasting it onto a text file, and don't see anything.

If the datatype is Datetime you should use Year() function to filter the rows instead of like. You should not use like operator to filter the data from Datetime type.
If the datatype is Datetime then you won't be having leading or trailing spaces.
You do have appropriate Date functions in Sql Server use those to filter the rows.
select mydate from mytable where year(mydate) = 2010
or even Datepart
select mydate from mytable where Datepart(YYYY,mydate) = 2010

You have to convert datetime that first in varchar to use like
select mydate from mytable
WHERE CONVERT(VARCHAR(10),mydate,120) like '2010%'
DEMO

You probably should use just date range fetches, for example
select mydate from mytable where mydate >= '20100101' and mydate < '20110101'
Using functions for the column (e.g. year(mydate)) is not a good idea because then indexes can't be used. Using 'between' can also cause problems with datetime columns because the time part can cause you to accidentally leave out rows.
The reason you found something with your search is probably due to typecasting the date into varchar before comparison, and format is such that the year is at the end, but please don't use that.

Related

SQL number Wildcard issue

I'm trying to add a wildcard to my date select query so i only pull the day not time. I.e. 2021-03-11 17:54:30.123. I thought a number could be substituted for a #.
select AID, LocalCoAltIn,LocalCoAltOut,EventTime
from EXCDS.dbo.WKS_LOG_VIEW
where EventTime like '2021-03-11 ##:##:##:###';
My query is returning no values even though they are in the table. Thanks.
No! Don't use strings! One method is to convert to a date:
select AID, LocalCoAltIn,LocalCoAltOut,EventTime
from EXCDS.dbo.WKS_LOG_VIEW
where convert(date, EventTime) = '2021-03-11';
Another method is to use a range:
where EventTime >= '2021-03-11' and
EventTime < '2021-03-12'
The LIKE operator in most flavors of SQL only support _ and * wildcards (matching any one single, or multiple characters). Gordon has given you a better approach, but if you wanted to fix your current query on SQL Server you could try:
SELECT AID, LocalCoAltIn, LocalCoAltOut, EventTime
FROM EXCDS.dbo.WKS_LOG_VIEW
WHERE EventTime LIKE '2021-03-11 [0-9][0-9]:[0-9][0-9]:[0-9][0-9]:[0-9][0-9][0-9]';
SQL Server extended the LIKE operator to accept a few extra things, such as character classes. Here [0-9] inside LIKE would match any single digit.
Not sure that like operator would work for date as you want, but you still have few options.
Use DATEPART function to retrieve year\month\etc and compare it with exact value that you need
select AID, LocalCoAltIn,LocalCoAltOut,EventTime from EXCDS.dbo.WKS_LOG_VIEW where DATEPART(year,EventTime) = 2021 AND DATEPART(month,EventTime) = 3 AND DATEPART(day,EventTime = 11);
Or use Gordon Linoff suggestion if you dont care about exact date part and only need to compare entire date without time

Select a date in a string and convert it to datetime

I have a string like:
'SPY US 03/20/20 P45'
I want to select just the date from the string.
My current query is:
Select Ticker, SUBSTRING(Ticker, PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9]%',o.Ticker),8) AS 'myDate' FROM TABLE
This returns: 'SPY US 03/20/20 P45', 03/20/20
I want myDate to be in datetime.
I have tried various morphs of cast and convert, but they fail, presumably because they want the format to be in YYYY-MM-DD rather than MM/DD/YY.
My "smartest" attempt to convert was this:
CONVERT(DATETIME, SUBSTRING(o.Ticker, PATINDEX('%[0-9][0-9]/[0-9][0-9]/[0-9][0-9]%',o.Ticker),8),1)
After reading style guidelines here: https://www.w3schools.com/sql/func_sqlserver_convert.asp
but it still failed.
The ideal end-format for the date would be YYYY-MM-DD
Edited to add:
I have been fiddling with it and realized that I over simplied my question. The convert works if I just test it on a string, but the entire query involves several joins.
As I can understand you are looking for something like this.
You can use string_split() function to split string with blank space and then use try_cast() function to check each value whether it is a date.
declare #string as varchar(120) = 'SPY US 03/20/20 P4'
; with cte as (select
value
from string_split (#string, ' ')
)Select value from cte where try_cast (value as datetime) is not null
Live db<>fiddle demo.
So it turns out that there were a few entries in the column that didn't have friendly date format, so the patindex clause was returning nonsense.
For some reason that caused the entire operation to fail(rather than just returning null on the few entries that were failing).
Once I selected the entire (ultimately more complicated join statement) into a temp table, then I was able to try_convert the substring into a date and run my operations.

SQL:how to perform select only on some characters from a column

I wanted to know how to perform the SQL SELECT operation on only a particular range of characters.
For example,I've got an SQL query:
SELECT date,score from feedback GROUP BY date
Now this date is of format yyyy/mm/dd.
So I wanted to strip the days or cut out the days from it and make it yyyy/mm, thereby selecting only 0-7 characters from the date.
I've searched everywhere for the answer but could not find anything.Could I maybe do something like this?
SELECT date(7),score from feedback GROUP BY date(7)
In MSQL you use LEFT other use substring
SELECT LEFT('abcdefg',2);
--
ab
So in your case
SELECT LEFT(date,7), score
FROM feedback
GROUP BY LEFT(date,7)
But again things will be much easier if you use a date field instead a text field.
Assuming that your date field is an actual date field (or even a datetime field) the following solution would work:
select left(convert(date ,getdate()),7) as Year_Month
Changing getdate() to your date field, it would look like:
select left(convert(date , feedback.date),7) as Year_Month
Both queries return the following:
2016-01

Strange behaviour of Sql query with between operator

There is this strange error in sql query.
The query is something like this.
select * from student where dob between '20150820' and '20150828'
But in the database the column of dob is varchar(14) and is in yyyyMMddhhmmss format,Say my data in the row is (20150827142545).If i fire the above query it should not retrive any rows as i have mentioned yyyyMMdd format in the query.But it retrives the row with yesterday date (i.e 20150827112535) and it cannot get the records with today's date (i.e 20150828144532)
Why is this happening??
Thanks for the help in advance
You can try like this:
select * from student
where convert(date,LEFT(dob,8)) between
convert(date'20150820') and convert(date,'20150828'))
Also as others have commented you need to store your date as Date instead of varchar to avoid such problems in future.
As already mentioned you would need to use the correct date type to have between behave properly.
select *
from student
where convert(date,LEFT(dob,8)) between '20150820' and '20150828'
Sidenote: You don't have to explicitly convert your two dates from text as this will be done implicitly as long as you use an unambiguous date representation, i.e. the ISO standard 'YYYYMMDD' or 'YYYY-MM-DD'. Of course if you're holding the values in variables then use date | datetime datatype
declare #startdate date
declare #enddate date
select *
from student
where convert(date,LEFT(dob,8)) between #startdate and #enddate
Sidenote 2: Performing the functions on your table dob column would prevent any indexes on that column from being used to their full potential in your execution plan and may result in slower execution, if you can, define the correct data type for the table dob column or use a persistent computed column or materialised view if your performance is a real issue.
Sidenote 3: If you need to maintain the time portion in your data i.e. date and time of birth, use the following to ensure all records are captured;
select *
from student
where
convert(date,LEFT(dob,8)) >= '20150820'
and convert(date,LEFT(dob,8)) < dateadd(d,1,'20150828')
All you have to do is to convert first the string to date.
select *
from student
where dob between convert(date, '20150820') and convert(date, '20150828')
Why is this happening?
The comparison is executed from left to right and the order of characters is determined by the codepage in use.
Sort Order
Sort order specifies the way that data values are sorted, affecting
the results of data comparison. The sorting of data is accomplished
through collations, and it can be optimized using indexes.
https://msdn.microsoft.com/en-us/library/ms143726.aspx
There are problems with between in T-SQL.
But if you want a fast answer convert to date first and use >= <= or even datediff to compare - maybe write a between function yourself if you want the easy use like between and no care about begin and start times ...
What do BETWEEN and the devil have in common?

Find record between two dates

When I write below query it gives record .
SELECT [srno],[order_no],[order_date],[supplier_name],[item_code],[item_name],[quntity]
FROM [first].[dbo].[Purchase_Order]
WHERE order_date BETWEEN '22/04/2015' AND '4/05/2015'
In this query if I don't add 0 in '4/05/2015' it returns record.
But when I add 0 to the date i.e. '04/05/2015' it doesn't give any records.
SELECT [srno],[order_no],[order_date],[supplier_name],[item_code],[item_name],[quntity]
FROM [first].[dbo].[Purchase_Order]
WHERE order_date BETWEEN '22/04/2015' AND '04/05/2015'
The reason it's not working because SQL is trying to do a string comparison because both your types are string types, But what you really want to do a date comparison.
You should do something like this. Since you only need date part you can strip off the time and use style 103 for your format dd/mm/yyyy.
WHERE CONVERT(DATETIME,LEFT(order_date,10),103)
BETWEEN CONVERT(DATETIME,'20150422') AND CONVERT(DATETIME,'20150504')
Alternately you can use this as well if your order_date has dates like this 5/4/2015 03:20:24PM
WHERE CONVERT(DATETIME,LEFT(order_Date,CHARINDEX(' ', order_Date) - 1),103)
BETWEEN CONVERT(DATETIME,'20150422') AND CONVERT(DATETIME,'20150504')
A long term solution is to change your column order_date to DATE/DATETIME
It Better to Cast it to date rather than depend on IMPLICIT conversion
SELECT [srno],[order_no],[order_date],[supplier_name],[item_code],
[item_name],[quntity] FROM [first].[dbo].[Purchase_Order] where
convert(date,order_date,105) BETWEEN cast('22/04/2015' as Date) AND cast('04/05/2015' as date)