Update table based on last date of previous month - sql

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.

Related

Load data for Last month when Insert date > 10th day of the month

I have a fact Table For eg Table X. I need to write a query to load last month data only when the insert date is greater than 10th of the month.
You can get the 10th day of the current month with an expression like:
datefromparts(year(getdate()), month(getdate()), 10)
If you want to compute this from a table column, you can just replace getdate() with the relevant column name.
It is rather unclear how you want to use this computation in your query though. If you want to filter the table for insert_dates greater than the 10th of the current month, you would do:
select * from tablex where insert_date >= datefromparts(year(getdate()), month(getdate()), 10);
If you want to filter on the 10th of each month, then:
select * from tablex where day(insert_date) >= 10

Display rows in SQL where the difference between columns is 1 day

I have joined 3 tables to provide a date of birth and a date of death. I now need to filter these results to display when the elapsed time between Birth and Death is 1 day, 2 days etc.
I am struggling to work out how I can do this. The date format is 2007-12-07 so I can't do a multiple of seconds on this.
Maybe this is what you are looking at with the limited information provided. This is specific to SQL Server.
DECLARE #Date TABLE
(
[DoB] date,
[DoD] date
)
INSERT INTO #Date
VALUES('2007-12-07','2007-12-08'),('2007-12-07','2007-12-10'),('2008-05-17','2020-07-02'),('2009-10-07','2015-12-25')
SELECT [DoB],
[DoD],
DATEDIFF (d, [DoB], [DoD]) AS NumOfDays
FROM #Date
ORDER BY NumOfDays

Update age column by one year

How to update the age column by only one year for each row in the table,
so how to get the year of that column and increase it by 1.
My data looks like:
ID name age
1 sarah 1992-05-26 00:00:00
2 suzan 1991-05-20 00:00:00
For your specific question you can add one year onto each date with a simple DateAdd:
UPDATE DataTable SET Age = DATEADD(year, 1, Age)
However, I would store the Date of Birth in the database and calculate the Age in the Business Layer or wherever it needs to be displayed.
For reference, if you do store the Date of Birth, then the age can be calculated with a simple query using a DateDiff function to calculate the number of whole years between the date of birth and todays date:
SELECT DT.Name
, DT.DateOfBirth
, DATEDIFF(year, DT.DateOfBirth, GETDATE()) As Age
FROM DataTable DT
your query should look like this:
Update yourTable set age = DATEADD(yy,1,age)
this will increase year by 1

Which is more efficient for Selecting records that 'happened' - from 00:00:00 to 23:59:59 of a date in a another record, in the same JOIN

I would like to fetch data for records for a given date/ 1 day interval.
This means from 00:00:00 to 23:59:59 of that day. The date value comes from another table in a join statement... i.e, it's not a parameter.
Suppose I have a Transactions table with a DateOccured (Datetime) field
From my research, I have two possible options(amongst others).
Calculate the datetime range values for that day
From 00:00:00
DateAdd(dd, DateDiff(dd,0,Transaction.DateOccured,0)
To 23:59:59
DateAdd(dd, 1, DateAdd(ss, -1, CONVERT(DATE,Transaction.DateOccured))) -- 1 second before midnight of following day
(several options of doing this, e.g placing this in the SELECT list or placing it in the WHERE clause)
Convert Datetime to date then append appropriate strings(for the time portion) to create the range (does not seem efficient)
Which would be the best strategy?
Would I place this calculation in the SELECT list and use as a field in the WHERE? or is it better of in the WHERE clause
The simplest method is:
on cast(t.dateoccurred as date) = t2.otherdate
This could use an index on the first table (see Martin Smith's comment). It can definitely take advantage of an index on the second table.
The following version could also use an index on the first table but not the second:
on t.dateocurred >= t2.otherdate and
t.dateoccurred < dateadd(day, 1, t2.otherdate)

Name Change SQL Query - Positive Attrition

Using SQL Server Management Studio and I've got an Employee table which has records for every time something changes with an employee, be it manager, pay-scale, etc. etc. etc. Whenever a change is made, and EffectiveEndDateKey will be marked for the last time that complete field was relevant and the next record will have the next day as and EffectiveBeginDateKey.
What I'm trying to do is extract the last record an employee had BEFORE they changed their job title in the last month. The goal is IF an employee changes their job title within a given month that would count as "Positive Attrition" and we're trying to figure out how much positive attrition we get in a given month. (It's always for the previous month so in the where statement I'm pulling just changes for the previous month).
Take a look below:
In this example, on July 4th, John Doe went from being an Apple Store Clerk to the next day being a manager, so there was a job title change. What I want is to pull the record in the red box (Jon's last day - in July - when her was an Apple Store Clerk before he became a manager) b/c that tells me that an EffectiveEndDateKey had a change that resulted in a job title change.
So the where statement is going to have a Cast in it to convert the EffectiveEndDateKey to a date and then look at last months data, pulling only records that have EffectiveEndDateKeys from last month (July) and what I need help with is the part where those records must ALSO have a different job title.
if say someone changed job titles on July 31st (so their new job title/EffectiveBeginDateKey was 20130801), that would still count as 1 positive attrition and we'd want to pull the last record from July 31st.
Any thoughts?
You can do this with a self-join:
select eprev.*
from Employee e
Employee eprev
on e.EmployeeId = eprev.EmployeeId and
cast(cast(e.EffectiveBeginDateKey as varchar(255)) as datetime) =
cast(cast(eprev.EffectiveEndDateKey as varchar(255)) as datetime) + 1
where cast(cast(e.EffectiveBeginDateKey as varchar(255)) as datetime) >= dateadd(mm, -1, getdate()) and
eprev.JobTitle <> e.JobTitle;
The key here is the conversion of the number to a datetime. The format YYYYMMDD is easily convertible, when it is a string. So, convert the number of a string first, then to a datetime. The rest is just the mechanics of the join.
Since your strings are effectively just dates in ISO format (yyyymmdd), you don't even have to convert it to datetime, you could just get previous row:
select E.EmployeeID, E.JobTitle, ENEXT.JobTitle as NextJobTitle
from Employee as E
outer apply (
select top 1 T.JobTitle
from Employee as T
where
T.EmployeeID = E.EmployeeID and
T.EffectiveEndDateKey > E.EffectiveEndDateKey
order by T.EffectiveEndDateKey asc
) as ENEXT
where
E.JobTitle <> ENEXT.JobTitle and
E.EffectiveEndDateKey >= convert(nvarchar(8), dateadd(mm, datediff(mm, 0, getdate()) - 1, 0), 112)
see SQL FIDDLE example