Subtract substring days from date - sql

I'm trying to come up with a Select statement that would return the DATE column minus the number of days in the DAYS column.
This is the query I tried:
SELECT
DATEADD(DAY, -+(REPLACE(ISNULL(DAYS,0), 'DAYS', '')), DATE)
FROM
T
It throws an error
Operand data type varchar is invalid for minus operator

dateadd(day, -1*convert(int, coalesce(replace([DAYS], ' days', ''),'0')), [DATE])

Something like
DECLARE
#Days VARCHAR(25) = '23 DAYS',
#Date DATE = '2018-10-23';
SELECT DATEADD(Day, - CAST(REPLACE(#Days , 'DAYS', '') AS INT), #Date )
If you are using SQL Server 2012+
SELECT DATEADD(Day, - ISNULL(TRY_CAST(REPLACE(#Days , 'DAYS', '') AS INT), 0), #Date )

I think you need to get the number, cast it to integer as negative and use dateadd like below:
SELECT dateadd(DAY,cast('-'+substring([DAYS], 1,charindex(' ',[DAYS])) as int),[DATE])
FROM T

You can use this:
Use CHARINDEX to get the number of days and convert to int
and then minus it from date column
select DATEADD(DAY,-CAST(SUBSTRING(days,1,CHARINDEX(' ',days)) AS INT),DATE),* from #table

The DATEADD function expects an integer for its second parameter argument.
By REPLACING 'DAYS' with an empty string, you are still left with a varchar containing a number and the blank space that was between that number and the word "DAYS".
RTRIM this result and CAST it as an Integer, and you should be good to go.
Oh, and you also need to put ,DATE inside the DATEADD()'s parenthesis.

Related

how to get this results for this?

Write a SELECT statement that returns these columns from the db1.MyGuitarShop.Products table:
a) The DateAdded column
b) A column that uses the CAST function to return the DateAdded column with its date only (year, month, and day)
c) A column that uses the CAST function to return the DateAdded column with its full time only (hour, minutes, seconds, and milliseconds)
d) A column that uses the CAST function to return the DateAdded column with just the month and day
This is what I have currently:
SELECT
DateAdded,
CAST(DateAdded AS decimal(10, 1)) AS AddedDate,
CAST(DateAdded AS decimal(10)) AS AddedTime,
CAST(DateAdded AS int) AS AddedChar7
FROM MyGuitarShop.Products;
With CAST converting to a DATE and TIME is easy. But the third item is trickier and involves two separate CASTS's, followed by string concatenation.
Something like this shoul do the trick:
Note that I've subbed in a variable (#dt) just to make it simpler to demonstrate the concept.
DECLARE #dt DATETIME = GETDATE()
SELECT #dt
, CAST(#dt AS Date) AS AddedDate
, CAST(#dt AS Time) AS AddedTime
, CAST(MONTH(#dt) AS VARCHAR(4)) + CAST(DAY(#dt) AS VARCHAR(4)) AS AddedChar
Here is a fiddle
Another options would be to use CONVERT to convert the dates to text. It has the advantage of allowing you to choose a specific format for the results ...
https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver15
SELECT
DateAdded,
CONVERT(varchar(128), DateAdded, 111) AS AddedDate,
CONVERT(varchar(128), DateAdded, 14) AS AddedTime,
CAST(DATEPART(MONTH, DateAdded) as varchar(2)) + '/' + CAST(DATEPART(DAY, DateAdded) as varchar(2)) AddedChar7
FROM (VALUES
(GETDATE())
)Products(DateAdded)
SELECT DateAdded
,Cast(DateAdded as date) Cast_YMD --Default for date is YMD
,Cast(DateAdded as time) Cast_HMSM -- Default for time is HMSM
,CAST(DateAdded as char(6)) Cast_MMDD --The 6 characters in the date field are month(as 3 char name Jan,Feb...) and day(as 2 digit)
FROM Products

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'))

Subtract one month from mm/yy in SQL

How can I subtract one month from mm/yy in SQL?
For an example from 02/23 to 01/23.
Since your date format is not the recommended one. But for your scenario, you can use the following query to get your expected result.
Using DATEFROMPARTS() and string functions you can construct as a date and the DATEADD(MONTH, -1, date) will help to subtract one month.
DECLARE #TestTable TABLE (DateVal VARCHAR(5));
INSERT INTO #TestTable (DateVal) VALUES ('02/23'), ('01/23'), ('03/30');
SELECT DateVal,
RIGHT(CONVERT(VARCHAR(8), DATEADD(MONTH, -1, DATEFROMPARTS(RIGHT(DateVal, 2), LEFT(DateVal, 2), '01')), 3), 5) AS Result
FROM #TestTable
Result:
DateVal Result
----------------------
02/23 01/23
01/23 12/22
03/30 02/30
Demo on db<>fiddle
I think you need to use convert() to get a valid date, then dateadd() to subtract 1 month and finally format() to get the date in the string format:
select
format(dateadd(month, -1, convert(date, concat('01/', datecolumnname), 3)), 'MM/yy')
from tablename
See the demo.
This comes with a warning is super ugly but if you want string previous month then string again, maybe convert to date do the dateadd then back to string, horrid!
with cte_d
as
(select '01/23' as stringdate
union
select '12/17' as stringdate
)
select stringdate
,cast(Month(dateadd(month,-1,cast(right(stringdate,2)
+ left(stringdate,2) + '01' as date))) as nvarchar(2))
+'/'+
right(cast(Year(dateadd(month,-1,cast(right(stringdate,2)
+ left(stringdate,2) + '01' as date))) as nvarchar(4)),2) as [NewDate]
from cte_d

How do I concatenate numbers to create a custom date?

Here is what I have tried thus far:
select CAST(
DATEPART(month,getDate())+'-'+
DATEPART(day,getDate())+'-'+
2012
as datetime)
I end up with the date: 1905-08-02 00:00:00.0. I was expecting to get today's date. I have rearranged the order and it doesn't seem to change. Can anyone offer as to why it gives me this? For the record, I plan to use other values than 2012 for the year.
Thanks in advance.
CAST() each piece as a varchar first:
select
cast(
cast(DATEPART(month,getDate()) as varchar(2))+'-'+
cast(DATEPART(day,getDate()) as varchar(2))+'-'+
'2012' as datetime)
select CAST ('2012'+
CAST(DATEPART(month,getDate()) as char(2))+
CAST(DATEPART(day,getDate()) as char(2))
as datetime)
You have to concatenate strings. Your code is casting the number 2039 to date.
If the goal with this little exercise is to be able to change the year of a given date you can do like this instead.
declare #NewYear int = 2003
-- with time part
select dateadd(year, #NewYear - year(getdate()), getdate())
-- time part removed
select dateadd(year, #NewYear - year(getdate()), dateadd(day, 0, datediff(day, 0, getdate())))
This code will work, you need to make sure that you are concatenating same data types and use convert with specific DateTime Format:
SELECT CONVERT(DATETIME,
CAST(DATEPART(month,getDate()) AS NVARCHAR(50))
+'-'+CAST(DATEPART(day,getDate()) AS NVARCHAR(50))
+'-2012'
,121)

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