How can I update row U with the same ID2 and latest date. I am able to write the select clause:
SELECT ID2
, MAX(Date)
FROM TABLE
GROUP BY ID2
but I have problem with update clause.
I have table:
ID1 |ID2 |Date |U
1 1 2015-02-18 NULL
2 1 2015-02-11 NULL
3 2 2015-02-17 NULL
4 2 2015-02-14 NULL
5 2 2015-02-11 NULL
6 3 2015-02-14 NULL
7 3 2015-02-10 NULL
What I want to achive:
ID1 |ID2 |Date |U
1 1 2015-02-18 Update
2 1 2015-02-11 NULL
3 2 2015-02-17 Update
4 2 2015-02-14 NULL
5 2 2015-02-11 NULL
6 3 2015-02-14 Update
7 3 2015-02-10 NULL
I will do this using CTE with Row_Number window function
;with cte as
(
select ID1 ,ID2 ,Date ,U, Row_Number() over(partition by ID2 order by Date desc) rn
From Yourtable
)
update Cte set U = 'Update'
where RN=1
When there is a tie in max date per ID2 then use Dense_rank to update both the records.
;with cte as
(
select ID1 ,ID2 ,Date ,U, Dense_Rank() over(partition by ID2 order by Date desc) rn
From Yourtable
)
update Cte set U = 'Update'
where RN=1
One approach would be to use your SELECT...MAX query to filter the TABLE. Something like this;
UPDATE T SET U = 'UPDATE'
FROM T JOIN (
SELECT ID2
, MAX(Date) AS MaxDate
FROM TABLE
GROUP BY ID2) AS X ON X.ID2 = T.ID2 AND X.MaxDate = T.Date
One point to note about this approach is that if there is more than 1 record with the max Date per ID2 then all records with the max Date will be updated.
interesting way to achieve this:
UPDATE T1
SET T1.U='Update'
FROM TestTable T1
WHERE 0=(SELECT COUNT(1) FROM TestTable T2 WHERE T1.ID2=T.ID2 AND T1.Date<T2.Date)
I had a table like
ID UserID rupees time
1 1 200 2014-01-05
---------------------------------
2 1 500 2014-04-06
----------------------------------
3 2 10 2014-05-05
----------------------------------
4 2 20 2014-05-06
----------------------------------
I want the output lie
ID UserID Rupees time CumulativeSum
1 1 200 2014-01-05 200
-------------------------------------------------
2 1 500 2014-04-06 700
-------------------------------------------------
3 2 10 2014-05-06 10
-------------------------------------------------
4 2 20 2014-05-06 30
---------------------------------------------------
How can i get this table as purput
Please try using CTE:
;With T as(
select
*,
ROW_NUMBER() over(partition by UserId order by [time]) RN
from tbl
)
select
UserID,
rupees,
[time],
(select SUM(rupees)
from T b
where b.UserID=a.UserID and b.RN<=a.RN) CumulativeSum
from T a
For records with column value time increasing, try the below query:
select
UserID,
rupees,
[time],
(select SUM(rupees)
from tbl b
where b.UserID=a.UserID and b.[time]<=a.[time]) CumulativeSum
from tbl a
For SQL Server 2012 or later, you can use SUM() with an OVER clause that specifies a ROW clause:
declare #t table (ID int,UserID int,rupees int,[time] date)
insert into #t(ID,UserID,rupees,[time]) values
(1,1,200,'20140105'),
(2,1,500,'20140406'),
(3,2, 10,'20140505'),
(4,2, 20,'20140506')
select
*,
SUM(rupees) OVER (
PARTITION BY UserID
ORDER BY id /* or time? */
ROWS BETWEEN
UNBOUNDED PRECEDING AND
CURRENT ROW)
as total
from #t
Result:
ID UserID rupees time total
----------- ----------- ----------- ---------- -----------
1 1 200 2014-01-05 200
2 1 500 2014-04-06 700
3 2 10 2014-05-05 10
4 2 20 2014-05-06 30
DECLARE #t table (UserID INT,rupees INT,DateKey Date )
INSERT INTO #t VALUES
(1,200,'2014-01-05'),
(2,300,'2014-01-06'),
(2,800,'2014-03-06')
select UserID,
rupees,
DateKey,
(SELECT SUM(rupees)from #t t
where t.rupees <= tt.rupees) from #t tt
GROUP BY UserID,rupees,DateKey
Hope this too helps you.
DECLARE #tab TABLE (id INT,userId INT,rupees INT,[time] Date)
INSERT INTO #tab VALUES
(1,1,200 ,'2014-01-05'),
(2,1,500 ,'2014-04-06'),
(3,2,10 ,'2014-05-05'),
(4,2,20 ,'2014-05-06')
SELECT LU.id,LU.userId,LU.rupees,LU.time,SUM(b.rupees) CumulativeSum
FROM (SELECT *,ROW_NUMBER() OVER (PARTITION BY userId ORDER BY [time]) R FROM #tab) B
JOIN (SELECT *,ROW_NUMBER() OVER (PARTITION BY userId ORDER BY [time]) R FROM #tab) LU
ON B.userId = LU.userId AND B.R <= LU.R
GROUP BY LU.id,LU.userId,LU.rupees,LU.time
Result
I am assuming that you are not using SQL Server 2012, which provides the cumulative sum function. The other answers use some form of the row_number() function, but these seems totally unnecessary. I usually approach cumulative sums using correlated subqueries:
select ID, UserID, rupees, [time],
(select sum(rupees)
from table t2
where t2.UserId = t.UserId and
t2.ID <= t.ID
) as CumulativeSum
from table t;
This requires having a column that uniquely identifies each row, and that seems to be the purpose of id. For performance, I would want to have an index on table(UserId, ID, rupees).
select *, SUM(rupees) OVER (
PARTITION BY UserID
ORDER BY id) as CumSum from #tbl
I have a history of records (multiple records per update all with the exact same datetime) that share an IdString.
I want a query to determine which of these records are part of the most recent update group.
This query will show me one of the records having the most recent update date, but for each partition, I need all the records with that max date.
;with cte as(
select ROW_NUMBER() over (partition by IdString order by UpdateDate desc) as [rn], *
from MyTable
)
select CASE WHEN (cte.rn = 1) THEN 0 ELSE 1 END [IsOld], *
from MyTable m
inner join cte on cte.RecordId= m.RecordId
Would someone please help me figure out an appropriate query?
EDIT: Sample
(IsOld is the desired calculated value)
IsOld RecordId IdString UpdateDate
1 1 ABC 2011-06-16
1 2 ABC 2012-05-30
1 3 ABC 2008-12-31
0 4 ABC 2012-06-08
1 5 ABC 2011-01-16
0 6 ABC 2012-06-08
1 7 ABC 2012-06-07
1 8 XYZ 2001-01-16
1 9 XYZ 2013-01-30
0 10 XYZ 2001-01-31
1 11 XYZ 2013-06-01
1 12 XYZ 2001-05-04
0 13 XYZ 2013-01-30
SELECT CASE WHEN updateDate = maxDate THEN 0 ELSE 1 END isOldRecord, RecordID, IDString, UpdateDate
FROM
(
select m.RecordID, m.IDString, m.updateDate, MAX(UpdateDate) OVER (PARTITION BY IDString) maxDate
from MyTable m
) A
Try this -
;WITH cte AS(
SELECT RANK() OVER(PARTITION BY IdString ORDER BY UpdateDate DESC) AS [row_num], *
FROM MyTable
)
SELECT CASE WHEN m.[row_num] = 1 THEN 0 ELSE 1 END isOld, *
from cte m
I have a SQL Server 2008 table with the following data (Small sample)
id Date Value
20448D6F-4099-408D-85FE-11EC6690CDB8 2010-06-01 1
20448D6F-4099-408D-85FE-11EC6690CDB8 2010-06-02 2
20448D6F-4099-408D-85FE-11EC6690CDB8 2010-06-03 3
20448D6F-4099-408D-85FE-11EC6690CDB8 2010-06-04 4
20448D6F-4099-408D-85FE-11EC6690CDB8 2010-06-05 NULL
EF595DE6-FF57-4625-8254-287F49843445 2010-06-02 2
EF595DE6-FF57-4625-8254-287F49843445 2010-06-03 3
EF595DE6-FF57-4625-8254-287F49843445 2010-06-04 4
EF595DE6-FF57-4625-8254-287F49843445 2010-06-05 NULL
C6F459EF-1493-4864-81C2-E5B55283EF0C 2010-06-04 45
C6F459EF-1493-4864-81C2-E5B55283EF0C 2010-06-05 NULL
I am running the query
select *
from [test].[dbo].[testtable]
where id in
(
select id
from [test].[dbo].[testtable]
where Date='2010-06-05' and Value is null
)
and Date = DATEADD(D, -4, '2010-06-05')
which returns
id Date Value
20448D6F-4099-408D-85FE-11EC6690CDB8 2010-06-01 1
but when a record does not exist for 2010-06-01 I would like to return the next min date
So the results I would see from the sample would be
id Date Value
20448D6F-4099-408D-85FE-11EC6690CDB8 2010-06-01 1
EF595DE6-FF57-4625-8254-287F49843445 2010-06-02 2
C6F459EF-1493-4864-81C2-E5B55283EF0C 2010-06-04 45
I have millions of records how can I do this in a T-SQL query?
Thanks
You can use the MIN aggregate in a subquery:
SELECT t.Id, t.Date, t.Value
FROM [test].[dbo].[testtable] t
JOIN (
SELECT Min(Date) MinDate, Id
FROM [test].[dbo].[testtable]
WHERE Date >= '6/1/2010'
GROUP BY Id
) t2 ON t.Id = t2.Id AND t.Date = t2.MinDate
WHERE t.Id IN (
SELECT id
FROM [test].[dbo].[testtable]
WHERE Date='2010-06-05' and Value is null
)
SQL Fiddle Demo
have a temptable as follows
1. id empid triggerstatus
1 2881 null
2 2881 null
3 2881 null
4 2882 null
i need a sql query which will update the triggerstatus dynamically
to triggerstatus+1 if the empid is repected twice,trice,etc.
my result should look as
id empid triggerstatus
1 2881 1
2 2881 2
3 2881 3
4 2882 1
If you have SQL Server 2005+ you can use a CTE and ROW_NUMBER Windowing function:
WITH cte AS
(
SELECT id, empId, triggerStatus
, ROW_NUMBER() OVER (PARTITION BY empId ORDER BY id ASC) AS RowNumber
FROM yourTable
)
UPDATE t
SET triggerStatus = RowNumber
FROM yourTable AS t
INNER JOIN cte ON t.id = cte.id
You may want to add a WHERE clause if there are some records that you do not want to update triggerStatus for.