Mistyped dates in SQL - sql

I was wondering if there is a way to detect mistyped dates in SQL in a general sense.
For example:
Order1 - 2014
Order2 - 2104
Order3 - 2041
I am guessing a form of case statement using wildcards would do the trick. But I am kind of a beginner in that regard.
EDIT - Sorry, for clarification, my column actually contains YYYY-MM-DD. However, I am only concerned with the year formatting. The datatype is Date for TSQL.
Thank you!

Since your data is already in a date column you don't need to worry about whether the value is a valid date or not.
So basically you are looking - from what I can tell - to see if the date falls in an expected range.
So you might want to do something like
SELECT * FROM MYTABLE WHERE MYDATE NOT BETWEEN '01/01/1900' AND '12/31/2020'
(obviously you can make the range whatever values you want, either static values or values stored in an options table)
You could take this a step further and validate it on a dynamic range, something like this:
SELECT * FROM MYTABLE
WHERE MYDATE NOT BETWEEN DATEADD(YEAR, -5, GETDATE()) AND DATEADD(YEAR, 5, GETDATE())
A further step would be to validate it in a range, based on some other field in the table, such as a created-on date for the record, like this:
SELECT T.* FROM MYTABLE T
WHERE T.MYDATE NOT BETWEEN DATEADD(YEAR, -5, T.CREATEDON) AND DATEADD(YEAR, 5, T.CREATEDON)
This gives you a bit more flexibility, because the "incorrect" dates may actually be valid at another point in time.
This should give you some starting points from which you can flesh out your exact needs.

assuming you are using a varchar field (through the comments) try,
Where your_column not like '200_' or your_column not like '201_'
if you were using a int for year you could use a range
Where your_column not between 2000 and 2014

Related

Using REPLACE to change datetime with SET

I haven't used this website before and am very new to SQL so please excuse any errors or if this question has been raised incorrectly - I have been asked to do something that is well outside of my remit and skill level!
I have many rows of data with a particular column - COLUMN - which has a DATETIME datatype, in a particular table - let's call it _data, and the data within it looks like this: 2019-11-12 17:00:00.000
I want to replace the YY-MM-DD portion of all of the columns in this table with today's date, 2019-11-28.
I am trying this code:
update DATABASE.dbo._data
set COLUMN = REPLACE(COLUMN,'2019-11-13','2019-11-28')
Which executes and informs me that every row in DATABASE has changed, but when I look at the data with a SELECT statement, it is the same as it was before. Why is this, do I need to do something different because the datatype is DATETIME? Google did not elucidate me and neither did w3schools or the other questions I searched for on here, but that's probably because I have no idea what I am doing.
I am using SQL SERVER 2012 on a Windows Server 2012 R2 box and I am running this code with SQL Server Management Studio v18.4.
DATETIMEFROMPARTS is your best friend here.
DECALRE #now DATETIME = GETDATE();
UPDATE DATABASE.dbo._data
SET COLUMN = DATETIMEFROMPARTS(
YEAR(#now),
MONTH(#now),
DAY(#now),
DATEPART(hour, COLUMN),
DATEPART(minute, COLUMN),
DATEPART(second, COLUMN),
DATEPART(millisecond, COLUMN));
This seems like a really add logic, but seems like the "easiest" method would be to use DATEADD and DATEDIFF:
UPDATE dbo.YourTable
SET DateTimeColumn = DATEADD(DAY, DATEDIFF(DAY, DateTimeColumn, GETDATE()), DateTimeColumn);

Date Conversion in SQL

I have a date in following format in my DB.
10/16 - mm/yy
I need to convert it to:
October/16
Is this possible?
If it's not possible then please tell me why.
This is not a date, it's missing the day, it's a bad way to store year/month. There should be a 4 digit year to avoid confusion and the year should be listed first to enable correct sorting, e.g. '2016/10' or a numeric value 201610.
You can cast it to a DATE first and then use a FORMAT to disply only month/year:
set dateformat myd;
select format(cast(mystupidcolumn + '/1' as date), 'MMMM/yy')
Or SUBSTR the month part and use a CASE.
try this format,
SELECT DATENAME(month, DATEADD(month, #mydate-1, CAST('2008-01-01' AS datetime)))
You can display date by using this code
select datename(month, YourColumnName) + '/' + right(YEAR(YourColumnName),2)
FROM yourTableName
Simply change yourColumnName with name of your table column and yourTableName with name of table.
Yes you can, and it depend in what database you use to call date functions
If you column Datetime format
SQL server DATENAME(Month, GETDATE())
MySQL database MONTHNAME(now())
otherwise
convert it will in your choice at database or you code logic
split the value and lookup at month enum or fake the date to be accepted and complete date format like 01/10/16
so do something like SELECT DATENAME(Month, datecolumn) + '/' + YEAR (datecolumn)
also you can use instead of Year function DATEPART(yy,datecolumn)
the way you do it with format will look like
CONVERT(VARCHAR(11),GETDATE(),106)
but excepted to get first 3 char of month JUN

MM/DD comparison issue in SQL

I am using below SQL query to get data by mentioning date range without year.
Select * from table where Left(Convert(Varchar(10),Cast(createddate As Date),101),5) between '11/01' and '12/31'
The above query works say when the user enter the date range as '11/01' to '12/31'. But, when the user enters anything like '11/01' to '01/31' or '05/31' to 02/28' etc, the query is not returning any data.
Is it possible to make it work for above ranges?
I would use the month() function:
Select *
from table
where month(nm_birthdate) in (11, 12);
Your query, however, should work because 101 zero-pads days and months.
If you want to find birthdays between two dates in MM/DD format, you could do:
where (#startmmdd < #endmmdd) and convert(varchar(5), nm_birthdate, 101) between #startmmdd and #endmmdd) or
(#startmmdd > #endmmdd) and convert(varchar(5), nm_birthdate, 101) not between #endmmdd and #startmmdd)
There might be a little adjustment depending on whether or not you want to include the end points.
Notes:
The variables #startmmdd and #endmmdd need to be in MM/DD format. Leading zeros are needed for months and days less than 10.
Convert conveniently uses the length of the data type, so left() is not necessary.
Use DATEPART, something like this:
SELECT * FROM table WHERE datepart(month, birthdate) IN (11, 12)
Of course, you can combine it with:
datepart(day, birthdate)
in order to get more complex condition.
Hope it helps

how to remove time from datetime

The field DATE in the database has the following format:
2012-11-12 00:00:00
I would like to remove the time from the date and return the date like this:
11/12/2012
First thing's first, if your dates are in varchar format change that, store dates as dates it will save you a lot of headaches and it is something that is best done sooner rather than later. The problem will only get worse.
Secondly, once you have a date DO NOT convert the date to a varchar! Keep it in date format and use formatting on the application side to get the required date format.
There are various methods to do this depending on your DBMS:
SQL-Server 2008 and later:
SELECT CAST(CURRENT_TIMESTAMP AS DATE)
SQL-Server 2005 and Earlier
SELECT DATEADD(DAY, DATEDIFF(DAY, 0, CURRENT_TIMESTAMP), 0)
SQLite
SELECT DATE(NOW())
Oracle
SELECT TRUNC(CURRENT_TIMESTAMP)
Postgresql
SELECT CURRENT_TIMESTAMP::DATE
If you need to use culture specific formatting in your report you can either explicitly state the format of the receiving text box (e.g. dd/MM/yyyy), or you can set the language so that it shows the relevant date format for that language.
Either way this is much better handled outside of SQL as converting to varchar within SQL will impact any sorting you may do in your report.
If you cannot/will not change the datatype to DATETIME, then still convert it to a date within SQL (e.g. CONVERT(DATETIME, yourField)) before sending to report services and handle it as described above.
just use, (in TSQL)
SELECT convert(varchar, columnName, 101)
in MySQL
SELECT DATE_FORMAT(columnName, '%m/%d/%Y')
I found this method to be quite useful. However it will convert your date/time format to just date but never the less it does the job for what I need it for. (I just needed to display the date on a report, the time was irrelevant).
CAST(start_date AS DATE)
UPDATE
(Bear in mind I'm a trainee ;))
I figured an easier way to do this IF YOU'RE USING SSRS.
It's easier to actually change the textbox properties where the field is located in the report. Right click field>Number>Date and select the appropriate format!
SELECT DATE('2012-11-12 00:00:00');
returns
2012-11-12
Personally, I'd return the full, native datetime value and format this in the client code.
That way, you can use the user's locale setting to give the correct meaning to that user.
"11/12" is ambiguous. Is it:
12th November
11th December
For more info refer this: SQL Server Date Formats
[MM/DD/YYYY]
SELECT CONVERT(VARCHAR(10), cast(dt_col as date), 101) from tbl
[DD/MM/YYYY]
SELECT CONVERT(VARCHAR(10), cast(dt_col as date), 103) from tbl
Live Demo
TSQL
SELECT CONVERT(DATE, GETDATE()) // 2019-09-19
SELECT CAST(GETDATE() AS DATE) // 2019-09-19
SELECT CONVERT(VARCHAR, GETDATE(), 23) // 2019-09-19
In mysql at least, you can use DATE(theDate).
You may try the following:
SELECT CONVERT(VARCHAR(10),yourdate,101);
or this:
select cast(floor(cast(urdate as float)) as datetime);
Use this SQL:
SELECT DATE_FORMAT(date_column_here,'%d/%m/%Y') FROM table_name;

SQL statement between date

This is driving me crazy and not sure what I'm missing here..
so here is my data column looks like:
StartDateTime:
---------------
2012-01-17 11:13:46.530
2012-01-17 11:17:22.530
2012-02-17 11:31:22.223
here is my query trying to get:
select * from tablName
where convert(varchar(10), startDateTime, 101) between '2012-01-17' and '2012-01-17'
based on the above I should be getting TWO rows? but it does not, it return zero rows. what will be the correct way of doing?
PS:
I've looked at the MSDN site too:
Your query would only match dates that are between 2012-01-17 00:00:00 and 2012-01-17 00:00:00. So, the only matches would be when the date is exactly 2012-01-17 00:00:00.
Instead, I would do this:
declare #dateInput as DateTime
set #dateInput = '2012-01-17'
select *
from tablName
where startDateTime >= #dateInput
and startDateTime < dateadd(day, 1, #dateInput)
Note: SQL Server 2008+ has a new data type Date with no time component that can make these types of queries more readable.
There is now more information so I'll add a more appropriate answer.
The requirements are now a stored procedure passed a Date type parameter, not DateTime, and the desire is to return rows from a table based on criterion against a DateTime field named StartDateTime...
create procedure dbo.spGetEntriesForOneDay
#DesiredDate DateTime
as
SET NOCOUNT ON;
SET #DesiredDate = DATEADD(day, DATEDIFF(day, 0, #DesiredDate), 0)
SELECT Field1, Field2 -- see note 1
FROM dbo.TableName
WHERE StartDateTime >= #DesiredDate -- see note 2
AND StartDateTime < DATEADD(day, 1, #DesiredDate) -- see note 3
NOTE 1: Don't use * in production code, especially in a stored procedure. Besides being wasteful by returning columns you probably don't need and precluding the optimization of a covering index on a subset of the columns required you would need to recompile this stored procedure whenever the underlying table is altered in order to avoid unpredictable results.
NOTE 2: Avoid wrapping fields in functions. A field not wrapped in a function can potentially be matched by the optimizer to an index while a field wrapped in a function never will.
NOTE 3: #Martin Smith and #RedFilter are correct in that .997 precision assumes DateTime datatype forever; this approach is more future proof because is makes no assumptions of data type precision.
You're using a datetime field (I'm guessing).
Don't forget the time:
select * from tablName
where startDateTime between '2012-01-17' and '2012-01-17 23:59:59.997'
You can use the DateDiff function in the where clause. It would look like this:
select col1, col2 from tablName where DateDiff(day, startDateTime, #DesiredDate) = 0