SQL Server rows with latest date - sql-server

I have a table :
EventLog (
EventID (INT),
UserID (VARCHAR(50),
Event (NTEXT),
EventDate(DateTime),
DocuvmentID(INT)
)
I need to write a query to get the latest event, datetime for a bunch of userId which will be
WHERE UserID IN ( 'john','tom'...etc)
How can I do that?

SELECT y.UserID, y.Event, y.EventDate
FROM (SELECT UserId, MAX(EventDate) AS MaxDate
FROM YourTable
WHERE UserId IN ('john','tom',...)
GROUP BY UserId) t
INNER JOIN YourTable y
ON t.UserId = y.UserId
AND t.MaxDate = y.EventDate

With a simple CTE:
;WITH LatestDates AS
(SELECT
EventID, UserID,
Event, EventDate,
DocumentID,
ROW_NUMBER() OVER(PARTITION BY UserID ORDER BY EventDate DESC) AS 'RowNum'
)
SELECT *
FROM LatestDates
WHERE RowNum = 1 AND UserID IN (........)
This partitions your data by some criteria (I picked UserID as an option - might be something else for you), then numbers each group sequentially starting at 1, ordered by another criteria (here: EventDate DESC) - so the most recent event for each "partition" has RowNum = 1 which is what I select from that CTE

select
UserID,
MAX(EventDate) AS LatestEventDate
from
EventLog
where
UserID in ('john','tom')
group by
UserID

Related

Query table and Select latest 2 rows (in SQL Server)

I have a table that logs all updates made to an application. I want to query the table and return the last update by [Timestamp] and the update before that for a different value [ITEM]. I'm struggling to figure out how to get what i need. I'm returning more than one record for each ID and don't want that.
;WITH cte AS
(
SELECT
ID,
LAG(ITEM) OVER (PARTITION BY ID ORDER BY timestamp DESC) AS ITEM,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY timestamp DESC) RN
FROM
MyLoggingTable
WHERE
accountid = 1234
)
SELECT
cte.ID,
dl.ITEM,
DL.timestamp
FROM
cte
JOIN
MyLoggingTable DL ON cte.ID = DL.ID
WHERE
rn = 1
AND cte.ID IN ('id here | Sub select :( ..')
Is ID unique? Because if it is, your code shouldn't return duplicates. If it isn't, you will get duplicates because you are joining back to the MyLoggingTable which isn't needed. You should just move those columns (dl.Item & dl.timestamp) into the cte and return them from the cte like you did cte.ID.
I removed the LAG since you didn't return that column in your final query.
;WITH cte AS
(
SELECT
ID,
ITEM,
[timestamp],
--LAG(ITEM) OVER (PARTITION BY ID ORDER BY timestamp DESC) AS ITEM,
ROW_NUMBER() OVER (PARTITION BY ID ORDER BY timestamp DESC) RN
FROM
MyLoggingTable
WHERE
accountid = 1234
)
SELECT
cte.ID,
cte.ITEM,
cte.timestamp
FROM
cte
WHERE
rn = 1
AND cte.ID IN ('id here | Sub select :( ..')
Note, if you wanted the second to the last item, as you stated in your comments, make rn=2

Speeding up a SQL view by pre-filtering results

I have a view operating on a very large table.
CREATE VIEW [myView]
AS
-- first part
WITH A AS (
SELECT MAX(Id), ResultId, LocationId, TeamId
FROM VeryLargeTable
GROUP BY ResultId, LocationId, TeamId)
--second part
SELECT A.Id, A.TeamId, ROW_NUMBER() OVER (PARTITION BY ResultId, LocationId) RN
FROM A
WHERE RN = 1
GO
Now what I run operations such as
SELECT * from [MyView]
WHERE TeamId = 5
This is very slow because it is essentially executing
WITH A AS (
SELECT MAX(Id), ResultId, LocationId, TeamId
FROM VeryLargeTable
GROUP BY ResultId, LocationId, TeamId)
--second part
SELECT A.Id, A.TeamId, ROW_NUMBER() OVER (PARTITION BY ResultId, LocationId) RN
FROM A
WHERE RN = 1 AND TeamId = 5
What I want to know is how to structure this view so it will know to filter for TeamId = 5 in the first part so that, the following code, which is fast, executes
WITH A AS (
SELECT MAX(Id), ResultId, LocationId, TeamId
FROM VeryLargeTable
GROUP BY ResultId, LocationId, TeamId
WHERE TeamId = 5)
--second part
SELECT A.Id, A.TeamId, ROW_NUMBER() OVER (PARTITION BY ResultId, LocationId) RN
FROM A
WHERE RN = 1
You could rewrite your view as Inline TVF:
CREATE FUNCTION dbo.my_func(#TeamId INT)
RETURNS TABLE
AS
RETURN
(
WITH A AS (
SELECT MAX(Id), ResultId, LocationId, TeamId
FROM VeryLargeTable
WHERE TeamId = #TeamId OR #TeamId IS NULL
GROUP BY ResultId, LocationId, TeamId
)
--second part
SELECT A.Id, A.TeamId, ROW_NUMBER() OVER (PARTITION BY ResultId, LocationId) RN
FROM A
WHERE RN = 1
);
And query:
SELECT *
FROM dbo.my_fun(5)
WHERE ...

Finding a recent most duplicate records from SQL Server 2012

I want to find the recent duplicate records from SQL Server 2012. Here is the table structure I have.
I have table name called UserRegistration which contains the duplicate of UserID(GUID) and in same table, I have CreatedDate Column as well (Date). Now I want to find the recent duplicate records from this table.
Here is the same data.
id FirstName LastName CreatedDate UserID
109 FirstNameA LastNameA 28-04-2015 GUID1
110 FirstNameC LastNameD 19-05-2015 GUID2
111 FirstNameE LastNameF 22-05-2015 GUID1
If you notice on above tables, GUID 1 are having the duplicate, Now I want to find the recent one means it should return me only those rows with duplication but recent data. So in above table structure, it should return me 111 because record has been created recently compared to the 109. I believe you understand.
Do let me know if you have any question. I am happy to answer. Thanks. Awaiting for the reply.
Harshal
Try the below query this should do the work based on your i/p data -
create table #UserRegistration (id int,FirstName varchar(20),LastName varchar(20),CreatedDate date,UserID varchar(20))
insert into #UserRegistration
select 109, 'FirstNameA', 'LastNameA', '2015-04-28', 'GUID1' union
select 110, 'FirstNameC', 'LastNameD', '2015-05-19', 'GUID2' union
select 111, 'FirstNameE', 'LastNameF', '2015-05-22', 'GUID1'
select id, FirstName, LastName, CreatedDate, UserID from
(SELECT ur.*,row_number() over(partition by UserID order by CreatedDate) rn
FROM #UserRegistration ur) A
where rn > 1
You could use CTE. Group your records by UserID and give your particular row a rank ordered by CreatedDate.
insert into tab(id, FirstName, LastName, CreatedDate, UserID)
values(109, 'FirstNameA', 'LastNameA', '2015-04-28', 'guid1'),
(110, 'FirstNameC', 'LastNameD', '2015-05-19', 'guid2'),
(111, 'FirstNameE', 'LastNameF', '2015-05-22', 'guid1');
with cte as
(
select id, ROW_NUMBER() over (partition by UserID order by CreatedDate asc) as [Rank],
FirstName, LastName, CreatedDate, UserID
from tab
)
select id, FirstName, LastName, CreatedDate, UserID from cte where Rank > 1
Rank > 1 condition is responsible for retrieving duplicated items.
sqlfiddle link:
http://sqlfiddle.com/#!6/4d1f2/6
Solved this by using tmp-tables:
SELECT a.UserID,
MAX(a.CreatedDate) As CreatedDate
INTO #latest
FROM <your table> a
GROUP BY a.UserID
HAVING COUNT(a.UserID) > 1
SELECT b.id
FROM #latest a
INNER JOIN <your table> b ON a.UserID = b.UserID AND a.CreatedDate = b.CreatedDate
try this,
SELECT * FROM TableName tt WHERE
exists(select MAX(createdDate)
from TableName
where tt.UserID = UserID
group by UserID
having MAX(createdDate)= tt.createdDate)
I think your createddate field is not a date field, then try Format
WITH TempAns (id,UserID,duplicateRecordCount)
AS
(
SELECT id,
UserID,
ROW_NUMBER()OVER(partition by UserID ORDER BY id)
AS duplicateRecordCount
FROM #t
)
select * from #t where id in (
select max(id )
from TempAns
where duplicateRecordCount > 1
group by name )
You'd rank your records with ROW_NUMBER() to give all last records per userid #1. With COUNT() you make sure only to get the userids having more than one record.
select
id, firstname, lastname, createddate, userid
from
(
select
id, firstname, lastname, createddate, userid,
row_number() over (partition by userid oder by createddate desc) as rn,
count(*) over (partition by userid) as cnt
from userregistration
) ranked
where rn = 1 -- only last one
and cnt > 1; -- but only if there is more than one record for the userid
This gets the latest record for every userid that has duplicates.

How to extract the last records based on entrydate sql server

i have many duplicate job id but entry date is can not be duplicate. i need to fetch always unique job id based on last entry date. i have solved it with the below query but like to know is there any better way to form the same sql when data would be huge for best performance. please guide me thanks.
SELECT A.JID,A.EntryDate,RefundDate,Comments,Refund, ActionBy
FROM (
(
select JID, Max(EntryDate) AS EntryDate
from refundrequested
GROUP BY JID
) A
Inner JOIN
(
SELECT JID,ENTRYDATE,refundDate,Comments,refund,ActionBy
from refundrequested
) B
ON A.JID=B.JID AND A.EntryDate = B.EntryDate
)
Using the row_number() function is usually a bit faster:
select *
from (
select row_number() over (partition by jid
order by EntryDate desc) as rn
, *
from refundrequested
) as SubQueryAlias
where rn = 1
Query:
SELECT t1.JID,
t1.EntryDate,
t1.RefundDate,
t1.Comments,
t1.Refund,
t1.ActionBy
FROM refundrequested t1
LEFT JOIN refundrequested t2
ON t2.JID = t1.JID
AND t2.EntryDate > t1.EntryDate
WHERE t2.JID is null

get most recent IP address from log-in log

I have an activity log table on a site. There are columns for date/time, userID and IP address for each log-in.
I want to retrieve a list of unique usernames and the most recent IP address they logged in from.
What's the best way to retrieve this from the table using t-sql on SQL Server?
A portable approach is:
select l.userID, l.Date, l.IpAddress
from (
select userID, max(Date) as MaxDate
from Log
group by userID
) lm
inner join Log l on lm.userID = l.userID
and lm.MaxDate = l.Date
If you have SQL Server 2005+, you can also do:
select * from
(
select userID, Date, IpAddress,
Rank() over (Partition BY userID order by Date DESC) as Rank
from Log
) tmp
where Rank = 1
I'm guessing at some column / table names here, and I'm assuming username comes from a table (and you aren't storing the username in the log each time):
;WITH x AS
(
SELECT userID, IPaddress, rn = ROW_NUMBER() OVER
(PARTITION BY UserID ORDER BY datetimecolumn DESC)
FROM dbo.LogTable
)
SELECT u.username, x.IPAddress
FROM x INNER JOIN dbo.Users AS u
ON u.userID = x.userID
WHERE x.rn = 1;
select distinct(user_name), (select top 1 IP_address from log_table where user_name=LOG.user_name order by log_date desc)
from log_table LOG

Resources