Reputation: 55
I have the following data in a MYSQL table.
ID | NAME | PHONENO | TMDate | |
---|---|---|---|---|
1234 | Sarah | 0884100300 | 1-Jan-21 | |
1234 | Sarah | 0881500900 | 5-Mar-21 | |
1234 | Sarah | [email protected] | 10-Mar-21 | |
0001 | James | 09991234567 | 31-Dec-20 | |
0001 | James | [email protected] | 31-Dec-20 |
The table contain email and phone numbers for customers. If the phonenumber or email is updated, the data is recorded on a new row. The TMDate column shows when the record was collected.
I want the final output to be as follows:
ID | NAME | PHONENO | |
---|---|---|---|
1234 | Sarah | 0881500900 | [email protected] |
0001 | James | 09991234567 | [email protected] |
My approach was to first pull the phone numbers based on max data using script below and then pull the emails using a script with similar logic and then do inner join of the two
SELECT t1.id,
t1.name
t2.PHONENO,
t2.max_date
FROM phoneemail t1
INNER JOIN
(SELECT id,PHONENO, MAX(TMDATE) as max_date FROM phoneemail group by id,phoneno where t1.phoneno
is not null) t2
ON t1.id = t2.id
My approach is not working as I am still getting duplicate records
Upvotes: 1
Views: 76
Reputation: 164214
The columns PHONENO
and EMAIL
my have been updated in different dates, so getting the latest date for each ID will not help.
If your version of MySql is 8.0+ you can do it with FIRST_VALUE()
window function, which does not support IGNORE NULLS
, so conditional sorting is also needed:
SELECT DISTINCT ID, NAME,
FIRST_VALUE(PHONENO) OVER (PARTITION BY ID, NAME ORDER BY PHONENO IS NULL, TMDate DESC) PHONENO,
FIRST_VALUE(EMAIL) OVER (PARTITION BY ID, NAME ORDER BY EMAIL IS NULL, TMDate DESC) EMAIL
FROM phoneemail
For prior versions you need 2 correlated subqueries:
SELECT DISTINCT p1.ID, p1.NAME,
(SELECT p2.PHONENO FROM phoneemail p2
WHERE (p2.ID, p2.NAME) = (p1.ID, p1.NAME) AND p2.PHONENO IS NOT NULL
ORDER BY TMDate DESC LIMIT 1) PHONENO,
(SELECT p3.EMAIL FROM phoneemail p3
WHERE (p3.ID, p3.NAME) = (p1.ID, p1.NAME) AND p3.EMAIL IS NOT NULL
ORDER BY TMDate DESC LIMIT 1) EMAIL
FROM phoneemail p1
See the demo.
Results:
ID | NAME | PHONENO | |
---|---|---|---|
1234 | Sarah | 0881500900 | [email protected] |
0001 | James | 09991234567 | [email protected] |
Upvotes: 1
Reputation: 1271151
MySQL does not have a "first" or "last" aggregation function. So, one method is to use window functions:
select distinct id, name,
first_value(phone ignore nulls) over (partition by id order by tmdate desc) as phone,
first_value(email ignore nulls) over (partition by id order by tmdate desc) as email
from (select distinct id, name from t) t;
Happily, first_value()
has the ignore nulls
option.
Upvotes: 1