Get the lastest record with distinct values for a column - sql

I have the following data:
SalesID Source Name Modified On
S12345 ABC John 5/8/2013 5:44
S12345 ABC Tom 5/8/2013 5:45
S11111 EFG Sam 5/8/2013 5:46
S11111 EFG Don 5/8/2013 5:47
I want to write a SP or a query that will return me the 2nd and the 4th row i.e I want to write a query that will return the lasted modified records based on distinct sales ID.

Try Following:
select * from tableName where ModifiedOn=(select max(ModifiedOn) from tableName) group by SalesID

i used the following query and it worked just fine for me
SELECT * FROM (Select Asu_OrderId ,ModifiedOn ,ROW_NUMBER() OVER(PARTITION BY Asu_OrderId order by ModifiedOn desc)AS R from Asu_callreason
where <condition>) AS A WHERE r=1

Related

Select the latest NEW rows by Date from the Snapshot Table

I have a snapshot table like the following
id
name
value
date
123
ABC Corp
500
yesterday
123
ABC Corp
500
today
456
XYZ Ltd.
700
today
123
ABC Corp
500
tomorrow
456
XYZ Ltd.
700
tomorrow
789
PQR Consulting
100
tomorrow
I would like to get the new rows only like the following table from the above snapshot table using sql
id
name
value
date
456
XYZ Ltd.
700
today
789
PQR Consulting
100
tomorrow
I need a pointer whether to follow the window function (like LAG() etc.) to get the new table. or more simple solution is there? Thanks in advance!
There are a few options here, one of them is to use a cte or a derived table to add row_number based on the date column to the table, and the other is to use first_value window function. I'm pretty sure the derived table solution would be better in terms of performance, but I don't have the time to test.
Here's what I would do:
;WITH cte AS
(
SELECT id, name, value, date, ROW_NUMBER() OVER(PARTITION BY id ORDER BY date DESC) as rn
FROM snapshotTable
)
SELECT id, name, value, date
FROM cte
WHERE rn = 1;
To get the earliest records all you need to do is remove the DESC from the order by clause.

SQL Server: Select duplicate rows

I have a table:
personId
Date
location
abc123
15-09-2022
London
abc123
15-09-2022
Nottingham
efg321
12-09-2022
Leeds
abc123
13-09-2022
Birmingham
I want to select and return the duplicate rows based on Date and location columns, for example, in the above table: personId 'abc123' is present at location both 'London' and 'Nottingham' on the same date, so I would like to return these rows.
I have tried this query:
SELECT personId, Date FROM sampleTable GROUP BY personId, Date HAVING COUNT(*) > 1
But it gives me the count. I want the rows with all three columns. Expected result:
personId
Date
location
abc123
15-09-2022
London
abc123
15-09-2022
Nottingham
Can anyone please help me with this? Thanks
Try something like this:
SELECT
sampleTable.*
FROM
sampleTable
INNER JOIN -- acts as a filter here
(
SELECT
personId,
Date
FROM
sampleTable
GROUP BY
personId,
Date
HAVING
COUNT(*) > 1
) problemTable
ON sampleTable.personId = problemTable.personId
AND sampleTable.Date = problemTable.Date
ORDER BY
sampleTable.personId,
sampleTable.Date,
sampleTable.location
;
The derived problemTable calculates personId/Date combos that have multiple sampleTable rows. INNER JOINing sampleTable with problemTable, by nature of an INNER JOIN, returns an abridged version of sampleTable: one that only contains combos found within problemTable as well—and those are the ones you care about!
Using INNER JOIN as a filter mechanism is a common theme in SQL, so keep it in the back of your mind.
Its pretty easy using window functions.
Inner SQL returns same table with extra col that marks duplicate rows. Then outer sql filters rows that has duplicate
inner sql result
personid date location check
abc123 13-09-2022 Birmingham 1
abc123 15-09-2022 London 2
abc123 15-09-2022 Nottingham 2
efg321 12-09-2022 Leeds 1
final
personid date location check
abc123 15-09-2022 London 2
abc123 15-09-2022 Nottingham 2
SQL
WITH temp AS (
SELECT
personid,
datecol,
location,
COUNT( personid ) OVER (PARTITION BY personid, datecol) AS check
FROM sampletable
)
SELECT *
FROM temp
WHERE check > 1

How to select only the most recent

Table A has ID and date and name. Each time the record is changed the first 11 digits of the Id remain the same but the final digit would increase by 1. For example
123456789110 01-01-2020 John smith
119876543210 01-01-2020 Peter Griffin
119876543211 05-01-2020 Peter Griffin
How could I write a statement that shows The iD associated with John smith as well as the most recent Id of Peter Griffin? Thanks
Yet another option is using WITH TIES
Select top 1 with ties *
From YourTable
Order by row_number() over (partition by left(id,11) order by date desc)
Why not just use max()?
select name, max(id)
from t
group by name;

sql that identifies which account numbers have multiple agents

I dont think a count will work here, can someone help me get an sql that identifies which account numbers have multiple agents, more than two agents in the where condition.
AGENT_NAME ACCOUNT_NUMBER
Clemons, Tony 123
Cipollo, Michael 123
Jepsen, Sarah 567
Joanos, James 567
McMahon, Brian 890
Novak, Jason 437
Ralph, Melissa 197
Reitwiesner, John 221
Roman, Marlo 123
Rosenzweig, Marcie 890
Results should be something like this.
ACCOUNT_NUMBER AGENT_NAME
123 Cipollo, Michael
123 Roman, Marlo
123 Clemons, Tony
890 Rosenzweig, Marcie
890 McMahon, Brian
567 Joanos, James
567 Jepsen, Sarah
You can do this using window functions:
select t.account_number, t.agent_name
from (select t.*, min(agent_name) over (partition by account_number) as minan,
max(agent_name) over (partition by account_number) as maxan
from table t
) t
where minan <> maxan;
If you know the agent names are never duplicated, you could just do:
select t.account_number, t.agent_name
from (select t.*, count(*) over (partition by account_number) as cnt
from table t
) t
where cnt > 1;
Assuming your table name is test, this should pull all the records with duplicate ACCOUNT_NUMBER:
select * from test where ACCOUNT_NUMBER in
(select ACCOUNT_NUMBER from test
group by ACCOUNT_NUMBER having
count(ACCOUNT_NUMBER)>1)
order by ACCOUNT_NUMBER
Using count function u can get the result
CREATE TABLE #TEMP
(
AGENT_NAME VARCHAR(100),
ACCOUNT_NUMBER INT
)
INSERT INTO #TEMP
VALUES ('CLEMONS, TONY',123),
('CIPOLLO, MICHAEL',123),
('JEPSEN, SARAH',567),
('JOANOS, JAMES',567),
('MCMAHON, BRIAN',890),
('NOVAK, JASON',437),
('RALPH, MELISSA',197),
('REITWIESNER, JOHN',221),
('ROMAN, MARLO',123),
('ROSENZWEIG, MARCIE',890)
SELECT a.ACCOUNT_NUMBER,a.AGENT_NAME
FROM #TEMP A
JOIN(SELECT COUNT(1) CNT,
ACCOUNT_NUMBER
FROM #TEMP
GROUP BY ACCOUNT_NUMBER) B
ON A.ACCOUNT_NUMBER = B.ACCOUNT_NUMBER
WHERE B.CNT != 1

Create table with distinct values based on date

I have a table which fills up with lots of transactions monthly, like below.
Name ID Date OtherColumn
_________________________________________________
John Smith 11111 2012-11-29 Somevalue
John Smith 11111 2012-11-30 Somevalue
Adam Gray 22222 2012-12-11 Somevalue
Tim Blue 33333 2012-12-15 Somevalue
John NewName 11111 2013-01-01 Somevalue
Adam Gray 22222 2013-01-02 Somevalue
From this table i want to create a dimension table with the unique names and id's. The problem is that a person can change his/her name, like "John" in the example above. The Id's are otherwise always unique. In those cases I want to only use the newest name (the one with the latest date).
So that I end up with a table like this:
Name ID
______________________
John NewName 11111
Adam Gray 22222
Tim Blue 33333
How do I go about achieving this?
Can I do it in a single query?
Use a CTE for this. It simplifies ranking and window functions.
;WITH CTE as
(SELECT
RN = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [Date] DESC),
ID,
Name
FROM
YourTable)
SELECT
Name,
ID
FROM
CTE
WHERE
RN = 1
I think creating a table is a bad idea, but this is how you get the most recent name.
select name
from yourtable yt join
(select id, max(date) maxdate
from yourtable
group by id ) temp on temp.id = yt.id and yt.date = maxdate
JNK's CTE solution is an equivalent of the following.
SELECT
Name,
ID
FROM (
SELECT
RN = ROW_NUMBER() OVER (PARTITION BY ID ORDER BY [Date] DESC),
Name,
ID
FROM theTable
)
WHERE RN = 1
Trying to think a way to get rid of the partition function without introducing the possible duplicates.