How to change only the year of a date datatype - sql

I have a list of birthdays and the year is the only part that is incorrect. I have a list of ID #s for these individuals. Is there a way to change only the year for all of these people? I was thinking something like making a table of the query results and then using an UPDATE SET query, but I don't know how to only change the year.
Sample included in edit. Every year needs to be decreased by 2.

If all rows need to be decreased by two years, then:
UPDATE dbo.TableToUpdate
SET [Date Column] = DATEADD(YEAR, -2, [Date Column]);
If all rows need to be set to a specific year (say, 2019), and the column is date:
UPDATE dbo.TableToUpdate
SET [Date Column] = DATEFROMPARTS(2019, MONTH([Date Column]), DAY([Date Column]);
If all rows need to be set to a specific year (say, 2019) and the column is not date, you could use DATETIMEFROMPARTS or SMALLDATETIMEFROMPARTS, but at that point the following becomes shorter:
UPDATE dbo.TableToUpdate
SET [Date Column] = DATEADD
(
YEAR,
-DATEDIFF(YEAR, '20190101', [Date Column]),
[Date Column]
);

Here's the shortest I can think of, change the year to 2050:
select
dateadd(year, (2050 - year(d)), d)
from x
Sample data:
create table x(d date);
insert into x values
('2001-11-19'),
('2020-07-05'),
('2012-05-01');
Output:
COLUMN_0
2050-11-19
2050-07-05
2050-05-01
Live test: http://www.sqlfiddle.com/#!3/9a8b4/2

In case anyone else needs it for MySQL, here's the syntax:
UPDATE dbo.TableToUpdate
SET [Date Column] = DATE_ADD([Date Column], INTERVAL -2 year);

Related

Two columns with dates (one any day of week, another one WEEK ENDING DATE (SATURDAY) BASED ON 1st column)

I have such a situation.
I need to have 2 columns 1) Is just pull data from a table (just as it is) r.[RCLDTE] (Day of week)
and 2 column) I need to basically look at the first column and make it Saturday of that week.
SELECT r.[RCLDTE] AS 'Day of Week'
,r.[RCLDTE] AS 'Week Ending Day (Saturday)'
Before what I was doing at similar projects I just used this code and added to WHERE statement.
WHERE CONVERT(DATE, CONVERT(CHAR(8), r.[RCLDTE] )) = cast(DATEADD(dd, DATEPART(DW,GETDATE())*-1, GETDATE()) as date)
This code was changing the dates column to Saturday.
However, here I have a different situation. I need 2 columns 1) as it is and 2) where dates will be Saturdays of the week from r.[RCLDTE] column , as a result from the way how I understand I cannot use WHERE statement because it will affect both columns.
Does someone know how I can leave 1st column as it is and 2nd a column of Saturday.
Please let me know.
Thanks.
To avoid issues when someone changes either DATEFIRST or LANGUAGE settings, you can use this. Also, given that you are storing dates in a numeric column for some reason (you really should provide feedback to whoever owns the system so they can fix it), we have to first try to convert those values to a date (they may not all be valid, which is one of the problems with using the wrong data type):
;WITH t AS
(
SELECT *, ProperDate = CASE WHEN ISDATE(CONVERT(char(8), RCLDTE)) = 1
THEN CONVERT(date, CONVERT(char(8), RCLDTE)) END
FROM dbo.tablename
)
SELECT [Language] = ##language, [Datefirst] = ##datefirst,
RCLDTE = CASE WHEN ProperDate IS NULL THEN RCLDTE END,
[Day of Week] = ProperDate,
[Saturday] = DATEADD
(
DAY,
6 - ((DATEPART(WEEKDAY, ProperDate) + ##DATEFIRST - 1) % 7),
ProperDate
)
FROM t;
Updated db<>fiddle that also demonstrates the handling of garbage data and a version of SQL Server so old that TRY_CONVERT() didn't exist yet (at least 12 years ago).
here is one way :
select
r.RCLDTE AS 'Day of Week'
, dateadd(day, 7 - datepart(weekday, r.RCLDTE) , r.RCLDTE)
from tablename r
db<>fiddle here

Combine and convert nvarchar month field + float year field to a single date field

I have a table in SQL Server 2012 with a month column stored as nvarchar(255):
"January", "February", "March"
And another column in this table with year stored separately as float
"2012","2013,"2014".
I do not have a day column so I want to create a combined month date column with the day starting as 1.
So for month and year fields January 2012. I want to show '2012-01-01'
How can I do such and add that into my current table?
I want to find the maximum row for a record in my table for each employee.
so for an [employee #], [month],[year]. what is latest record so for example below:
1. 102, Jan, 2019
2. 102, feb, 2019
I want to only see the second record which is the latest.
SQL Server has pretty flexible conversion to date. So, just convert the columns to a date:
select convert(date, month + ' ' + year)
You can get the maximum as:
select empid, max(convert(date, month + ' ' + year))
from t
group by empid;
If you really like, you can change the format for output purposes. I would advise you to stick with a date, though.
Note: This assumes that your internationalization settings are set to English -- which seems reasonable if you are storing month names in English.
Fix your design! The way you store data makes it really inefficient to interpret it. Here, I think the simplest option is datefromparts() and a 12-branches case expression.
Assuming that the (float) year is stored in column col_year and the (string) month is in col_month:
select t.*,
datefromparts(
cast(col_year as int),
case col_month
when 'January' then 1
when 'February' then 2
...
when 'December' then 12
end,
1
) as date_col
from mytable t

Public holidays that fall on a sunday

I dont know about other countries but in South Africa we have a public holiday on a Monday if the Sunday was a Public holiday. I need to write an Update statement that will return the date after x number of days and should the date be a monday after a public holiday it should add an additional day. My simple update statement looks like:
UPDATE tbl_ProjectTracker
set Predicted_Date = DATEADD(DAY, 20, Actual_Eng_Start_date)
I already have a table for referencing but I am not sure if I should determine the additional day on the table or on the Update statement.
Please assist
You should have a PublicHoliday table
Then you could Update predicted_date like that
DECLARE #PublicHoliday AS TABLE
(
HolidayDate date
)
DECLARE #NumberDaysPredict int = 20
UPDATE pt
set pt.Predicted_Date = DATEADD(DAY, #NumberDaysPredict + hl.NumberHolidaysOnSunday, pt.Actual_Eng_Start_date)
FROM tbl_ProjectTracker pt
CROSS APPLY
(
SELECT Count(*) AS NumberHolidaysOnSunday
FROM #PublicHoliday ph
WHERE ph.HolidayDate BETWEEN pt.Actual_Eng_Start_date AND DATEADD(DAY, #NumberDaysPredict, Actual_Eng_Start_date)
AND Datepart(dw,ph.HolidayDate) = 1 -- Sunday
) hl
A simple way would be a case construct for the number of days:
UPDATE tbl_ProjectTracker
set Predicted_Date = DATEADD(
DAY,
CASE WHEN Actual_Eng_Start_date IN
(select day from public_holidays where datepart(dw, day) = 1) THEN 21 ELSE 20 END,
Actual_Eng_Start_date)
Unfortunately SQL Server's date / time functions are weak to say the least. The result of DATEPART(dw, ...) depends on a setting (DATEFIRST), so the query is kind of unreliable. Always make sure the setting is correct when you run it. It has been requested to extend DATEPART such as to accept an optional parameter for DATEFIRST so you'd get a consistent query, but Microsoft has closed this as "unsolvable" (https://connect.microsoft.com/SQLServer/feedbackdetail/view/432303/datepart-dw-date-should-allow-optional-date-first-Parameter).

Update table based on last date of previous month

Please would you advise how I could create a column which showed a timestamp/date for each row indicating the last day of the previous month. For example:
Name Surname DOB Timestamp
John Smith 1970/04/20 2015/02/28
Cindy Smith 1975/03/20 2015/02/28
Now this could be for 5000 people and I've just given 2 rows to show you what I mean.
CREATE table employees (Name NVARCHAR(30),Surname NVARCHAR (30),DOB DATETIME,Timestamp DATETIME)
To tackle the problem of the dates not showing hours,minutes, seconds, I am using
CONVERT(CHAR(10),Timestamp,113)
Do you use a While loop or something to create a column which shows the same timestamp for each row?
Thanks.
I think the easiest way is to just subtract the day of the month from the date:
select t.*, dateadd(day, -day(timestamp), timestamp)
from table t;
EDIT: In an `update:
update t
set timestamp = dateadd(day, -day(dob), dob)
In addition, you shouldn't use convert to remove the time component of a date, you should simply case to date. If dob had a time component (which seems unlikely):
update t
set timestamp = cast(dateadd(day, -day(dob), dob) as date)
Assuming the table have records with Timestamp column as NULL. Then with the following update query will update all records with previous month's last day.
UPDATE employees
SET [Timestamp] = CAST(DATEADD(DAY,-1,DATEADD(month, DATEDIFF(month, 0, GETDATE()), 0))AS DATE)
WHERE [Timestamp] IS NULL
The inner DATEADD will find first day of current month and outer DATEADD decrements the date by one which result in previous month's last date.
When the month in GETDATE() is April, the records with NULL values will be updated with 31-Mar-2015. When the GETDATE() becomes May, the records with NULL values will be updated with 30-Apr-2015 ie, it won't update the records which have already values or which are updated.

Select Date range between two months

My table has one [date] column and would like to filter dates between March to auguest for any year.
Here is my functions, but none of them work and returns all data.
iif(CDate([Date]) between DateAdd ("m",3, CDate([Date])) And DateAdd ("m",7,CDate([Date])),"1","0")
iif([Date of Activity] between (DatePart("m", [Date of Activity]) = 4) And (DatePart("m", [Date of Activity]) = 8),"1","0")
Date is a reserved word and should not be used for a field name. That said, the following should work if your field is a date/time field and not text. Month() Between 3 and 8