Need SQL MAX please - sql

I have a table with a list of Client No's, ID etc & there are many Clients with different ID's. I need to pull out the MAX ID No. for each Client, e.g.
ClientNo: 1500 has 3 ID's - the maximum in the ID field is the one I need!
UPDATE: This works:
SELECT MP.ClientID, MP.SequenceID
FROM TABLENAME MP
INNER JOIN (
SELECT ClientID, MAX(SequenceID) SequenceID
FROM TABLENAME
GROUP BY ClientID
) b on MP.ClientID = b.ClientID AND MP.SequenceID = b.SequenceID
BUT....
I need to link the table to many others to pull in other data, where do I insert the left joins to these tables please?

I am assuming you have multiple same client (numbers) with different IDs and for each client (number) you have to get the maximum ID. You may do the following:
select client_number, max(ID) from client group by client_number;
Depending on your need tweak this query.

You may want to do this:
SELECT MP.ClientID, b.DesiredValue
FROM TABLENAME MP
INNER JOIN (
SELECT ClientID, DesiredValue, ROW_NUMBER () OVER (PARTITION BY ClientID order by SequenceID desc) As RecentRN
FROM TABLENAME
) b
on MP.ClientID = b.ClientID AND b.RecentRN = 1
or
SELECT MP.ClientID, b.DesiredValue
FROM TABLENAME MP
INNER JOIN (
SELECT ClientID, DesiredValue,ROW_NUMBER () OVER (PARTITION BY ClientID order by SequenceID desc) As RecentRN
FROM TABLENAME
) b
on MP.ClientID = b.ClientID
Where b.RecentRN = 1

Related

SQL Join Multiple Tables and get the first row

I have a database where there are customers, phones, and addresses. Customers can have multiple phones and addresses and each phone and address record has a corresponding CustID. I'm trying to join these three tables and grab one phone and one address per customer, but cannot get this to work. The query returns one phone number per customer, but still return multiple addresses.
Here is my query:
SELECT customer_set.ID,
phone_set.cphone,
customer_set.Name,
address_set.Number,
address_set.Street
FROM (
SELECT ID, Name FROM CUSTOMER
) AS customer_set
LEFT JOIN PHONE AS phone_set
ON phone_set.CustID = (SELECT TOP 1 CustID
FROM PHONE
WHERE CustID = customer_set.ID
ORDER BY IsPrimary DESC)
LEFT JOIN ADDRESS AS address_set
ON address_set.CustID = (SELECT TOP 1 CustID
FROM ADDRESS
WHERE CustID = customer_set.ID
ORDER BY IsPrimary DESC)
Here you go:
SELECT
data.ID,
data.cphone,
data.Name,
data.Number,
data.Street
FROM (SELECT
customer_set.ID,
phone_set.cphone,
customer_set.Name,
address_set.Number,
address_set.Street,
ROW_NUMBER() OVER (PARTITION BY customer_set.ID ORDER BY customer_set.Name ASC) AS RowNum
FROM customer_set
LEFT OUTER JOIN PHONE
ON PHONE.CustID = customer_set.ID
LEFT OUTER JOIN ADDRESS
ON ADDRESS.CustID = customer_set.ID) AS data
WHERE data.RowNum = 1

Update data in table1 where duplicates in table2

I have 2 tables: Users and Results.
The usertable contains duplicate data which is reflected in the results table. The user below is created 3 times. I need to update the results table where UserId 2 and 3 to 1 so that all the results can be viewed on this user only.
This is easy if I have only have a few users and a few results for them, but in my case I have 500 duplicated users and 30000 results.
I am using SQL Server Express 2014
I will really appreciate any help with this!
Edit: misstyped column names in resultTable. Im sorry if you got confused by it.
UserTable
UserId---Fname---LName
1-----Georg-----Smith
2-----Georg-----Smith
3-----Georg-----Smith
ResultsTable
ResultId---UserRefId
1-----1
2-----2
3-----3
4-----1
I have manage to select duplicates from usertable, but i don't know how to proceed further.
;WITH T AS
(
SELECT *, COUNT(*) OVER (PARTITION BY Fname + Lname) as Cnt
FROM TestDatabase.Users
)
SELECT Id, Fname, Lname
FROM T
WHERE Cnt > 2
Your ResultTable has 2 columns with the same UserId name. I changed the second to UserId2 for the query below:
;WITH cte As
(
SELECT R.UserId, R.UserId2,
MIN(U.UserId) OVER (PARTITION BY U.FName, U.LName) As OriginalUserId
FROM ResultTable R
INNER JOIN UserTable U ON R.UserId = U.UserId
)
UPDATE cte
SET UserId2 = OriginalUserId
You are on the right track with the cte. The ROW_NUMBER() function can be used to flag duplicate UserIds, then you can join the cte into the from clause of your update statement to find the UserIds you want to replace, and join again to find the UserIds you want to replace them with.
;WITH cteDedup AS(
SELECT
UserId
,FName
,LName
,ROW_NUMBER() OVER(PARTITION BY FName, LName ORDER BY UserID ASC) AS row_num
FROM UserTable
)
UPDATE rt
SET UserId = original.UserId
FROM ResultsTable rt
JOIN cteDedup dupe
ON rt.UserId = dupe.UserId
JOIN cteDedup original
ON dupe.FName = original.FName
AND dupe.LName = original.LName
WHERE dupe.row_num <> 1
AND original.row_num = 1
See the SQLFiddle
A little tricky query looks like this:
;with t as (
select fname+lname name,id,
ROW_NUMBER() over(partition by fname+lname order by id) rn
from #users
)
--for test purpose comment next 2 lines
update #results
set userid=t1.id
--and uncomment the next one
--select t.name,t.id,userid,res,t1.id id1--,(select top 1 id from t t1 where t1.name=t.name and t.rn=1) id1
from t
inner join #results r on t.id=r.userid
inner join t t1 on t.name=t1.name and t1.rn=1
And then you can delete duplicate users
;with t as (
select name,id,
ROW_NUMBER() over(partition by name order by id) rn
from #users
)
delete t where rn>1

SQL - Select highest value when data across 3 tables

I have 3 tables:
Person (with a column PersonKey)
Telephone (with columns Tel_NumberKey, Tel_Number, Tel_NumberType e.g. 1=home, 2=mobile)
xref_Person+Telephone (columns PersonKey, Tel_NumberKey, CreatedDate, ModifiedDate)
I'm looking to get the most recent (e.g. the highest Tel_NumberKey) from the xref_Person+Telephone for each Person and use that Tel_NumberKey to get the actual Tel_Number from the Telephone table.
The problem I am having is that I keep getting duplicates for the same Tel_NumberKey. I also need to be sure I get both the home and mobile from the Telephone table, which I've been looking to do via 2 individual joins for each Tel_NumberType - again getting duplicates.
Been trying the following but to no avail:
-- For HOME
SELECT
p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1 -- e.g. Home phone number
AND pn.Tel_NumberKey = (SELECT MAX(pn1.Tel_NumberKey) AS Tel_NumberKey
FROM Person AS p1
INNER JOIN xref_Person+Telephone AS x1 ON p1.PersonKey = x1.PersonKey
INNER JOIN Telephone AS pn1 ON x1.Tel_NumberKey = pn1.Tel_NumberKey
WHERE pn1.Tel_NumberType = 1
AND p1.PersonKey = p.PersonKey
AND pn1.Tel_Number = pn.Tel_Number)
ORDER BY
p.PersonKey
And have been looking over the following links but again keep getting duplicates.
SQL select max(date) and corresponding value
How can I SELECT rows with MAX(Column value), DISTINCT by another column in SQL?
SQL Server: SELECT only the rows with MAX(DATE)
Am sure this must be possible but been at this a couple of days and can't believe its that difficult to get the most recent / highest value when referencing 3 tables. Any help greatly appreciated.
select *
from
( SELECT p.PersonKey, pn.Phone_Number, pn.Tel_NumberKey
, row_number() over (partition by p.PersonKey, pn.Phone_Number order by pn.Tel_NumberKey desc) rn
FROM
Persons AS p
INNER JOIN
xref_Person+Telephone AS x ON p.PersonKey = x.PersonKey
INNER JOIN
Telephone AS pn ON x.Tel_NumberKey = pn.Tel_NumberKey
WHERE
pn.Tel_NumberType = 1
) tt
where tt.rn = 1
ORDER BY
tt.PersonKey
you have to use max() function and then you have to order by rownum in descending order like.
select f.empno
from(select max(empno) empno from emp e
group by rownum)f
order by rownum desc
It will give you all employees having highest employee number to lowest employee number. Now implement it with your case then let me know.

sql get max of multiple results

In SQL server 2008 R2, how do you get the MAX result if you have two rows that have the same value? I have a table that I use to store the data about the number of times a client is seen at a location.
create table #templocation
(
ClientID Int,
Location Varchar(100),
LocationCount Int,
MaxCount Int
)
I only fill the first three columns with an insert statement then I get the max for each client like this:
update t
set t.MaxCount = t2.locationcount
from #templocation t
join (select tl.ClientID, MAX(tl.LocationCount) as 'locationcount'
from #templocation tl
group by tl.ClientID) t2
on t2.ClientID = t.ClientID
update t
set t.PrimaryLocation = tl.Location
from #temp t
join #templocation tl
on t.ClientId = tl.ClientID
where tl.LocationCount = tl.MaxCount
I then join this to the main table to get the final results. My problem is if a client is has two or more max counts. Then it wants to display all of the max locations like this:
ClientId Location LocationCount
12502 Main St. 4
12502 Lake Ave 4
12502 Tracy Rd 2
The results I get are:
ClientId ClientName Location
12502 John Smith Main St.
12502 John Smith Lake Ave
I only want the first or top one displayed though preferably by alphabetical order.
I do things like this through a couple of CTEs. One will give us the max(locationcount) for each client, and one just adds a row_number() for every clientid so we can pick the "first" location".
SQL Fiddle
It's a bit of a hack, but it works.
;with maxrows as
(select
ClientID as ClientID,
max(LocationCount) as MaxValue
--row_number() OVER (partition by ClientID order by ClientID)
from
table1
group by ClientID)
,
rowcounts as
(
select
t1.ClientID,
t1.Location,
row_number() over (PARTITION BY t1.ClientID order by t1.Location) as RowNum
from
table1 t1
)
select
t2.ClientID,
t2.Location
from
maxrows t1
inner join rowcounts t2
on t1.ClientID = t2.ClientID
and t2.rownum = 1
From how I understood the issue, you could use MAX() OVER () to achieve what you want like this:
WITH maxvalues AS (
SELECT
ClientId,
Location,
LocationCount,
MaxCount = MAX(LocationCount) OVER (PARTITION BY ClientId)
FROM atable
)
SELECT
ClientId,
Location
FROM maxvalues
WHERE LocationCount = MaxCount
;
Join maxvalues to whatever table holds the client names to include those into the output too.
Learn more about the OVER clause in this manual:
OVER clause (Transact-SQL)

Find the latest date of two tables with matching primary keys

I have two tables tables, each with primary keys for different people and the contact dates in each category.I am trying to find the most recent contact date for each person, regardless of what table its in. For example:
CustomerService columns: CustomerKey, DateContacted
CustomerOutreach columns: CustomerKey, DateContacted
And I'm just trying to find the very latest date for each person.
Use something like this.
You need to combine the two tables. You can do this by a union. There will be duplicates, but you just group by the customerKey and then find the Max DateContacted
SELECT * INTO #TEMP FROM (
SELECT
CustomerKey
, DateContacted
FROM CustomerService CS
UNION
SELECT
CustomerKey
, DateContacted
FROM CustomerOutreach CS
)
SELECT
CustomerKey
, MAX(DateContacted)
FROM #TEMP
GROUP BY
CustomerKey
Join your tables on primary keys and make a conditional projection.
Select cs.CustomerKey,
CASE WHEN cs.DateContacted <= co.DateContacted
THEN co.DateContacted
ELSE cs.DateContacted END
from CustomerService cs inner join CustomerOutreach co
on cs.CustomerKey = co.CustomerKey
I would do something like this.
Select b.customerKey, b.dateContacted
from (
select a.customerKey, a.DateContacted, Row_Number() over (Partition by customerKey order by DateContacted desc) as RN
from (
Select c.customerKey,
case when (s.DateContacted > o.dateContacted) then s.dateContacted else o.datecontacted end as DateContacted
from Customer c
left outer join customerService s on c.customerKey = s.customerKey
left outer join customerOutreach o on c.customerKey = s.customerKey
where s.customerKey is not null or o.customerKey is not null
)a
)b
where b.RN = 1
This solution should take care of preventing the case of having duplicates if both tables have the same max DateContacted.
http://sqlfiddle.com/#!3/ca968/1