Consider the 2 below tables
DETAILS table:-
email Name Region PostalCode
a@b.com Mike US-east 1234
a@b.com Sara US-east 2341
a@b.com Sara US-west 1234
b@c.com Ash US-west 6542
b@c.com Cindy US-west 4213
c@d.com George US-east 1234
c@d.com Thomas US-east 3412
EMAIL_STATUS table:-
email status
a@b.com In progress
c@d.com Resolved
I require a query that left joins the tables(left is DETAILS table and right is EMAIL_STATUS table) and fetches only one row for each email
expected result:-
email Name Region PostalCode status count(*)
a@b.com Mike US-east 1234 In progress 3
b@c.com Ash US-west 6542 null 2
c@d.com George US-east 1234 Resolved 2
I tried various queries but none seem to work in order to get the result i expect as it leads to errors due to group by.
This seems like a left join
with group by
:
select d.email, min(d.name) as name, min(d.region) as region,
min(d.postalcode) as postalcode,
es.status, count(*) as cnt
from details d left join
email_status es
on d.email = es.email
group by d.email, es.status;
The above returns one row for each email. If you want a particular row, then use row_number()
and count(*)
:
select d.*,
es.status, d.cnt
from (select d.*,
count(*) over (partition by email) as cnt,
row_number() over (partition by email order by ?) as seqnum -- the ? describes which row you want
from details d
) d left join
email_status es
on d.email = es.email;
Here's a slightly different approach, using LAG to determine if you're looking at the first line for a particular email address:
WITH DETAIL_COUNT AS (SELECT EMAIL, COUNT(*) AS EMAIL_COUNT
FROM DETAILS
GROUP BY EMAIL),
ALL_ROWS AS (SELECT d.EMAIL,
d.NAME,
d.REGION,
d.POSTAL_CODE,
e.STATUS,
dc.EMAIL_COUNT,
LAG(d.EMAIL, 1) OVER (ORDER BY d.EMAIL, d.NAME) AS PREV_EMAIL
FROM DETAILS d
LEFT OUTER JOIN EMAIL_STATUS e
ON e.EMAIL = d.EMAIL
LEFT OUTER JOIN DETAIL_COUNT dc
ON dc.EMAIL = d.EMAIL
ORDER BY d.EMAIL, d.NAME)
SELECT EMAIL, NAME, REGION, POSTAL_CODE, STATUS, EMAIL_COUNT
FROM ALL_ROWS
WHERE PREV_EMAIL IS NULL OR
PREV_EMAIL <> EMAIL
This produces the results:
EMAIL NAME REGION POSTAL_CODE STATUS EMAIL_COUNT
a@b.com Mike US-east 1234 In progress 3
b@c.com Ash US-west 6542 2
c@d.com George US-east 1234 Resolved 2
which I believe is what you're looking for.
Select d.email, min(d.name) As name, min(d.region) as region,
min(d.postalcode) as postalcode,
es.status, count(*) As cnt
From details d
Join email_status es
On d.email = es.email
Group By d.email;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.