问题
I have a SQL table consists of id, name, email,.... I have another SQL table that has id, email, emailstatus but these 2 id are different they are not related. The only thing that is common between these 2 tables are emails.
I would like to join these 2 tables bring all the info from table1 and if the email address from table 1 and table 2 are same and emailstatus is 'Bounced'. But the query that I am writing gives me more record than expected.
Can you help? Also I am not even sure that it is the right thing to do without a common id. This is my query.
SELECT
A.[Id]
,A.[Application]
,A.[Loan]
,A.[Firstname]
,A.[Lastname]
,A.[Email],
,H.[Email], H.[EmailStatus] as BouncedEmail
FROM Applicant A (NOLOCK)
left outer join [tbl_Webhook] [H] (NOLOCK)
on A.Email = H.Email
and A.Email is not Null and H.Email is not Null and H.[EmailStatus]='bounced'
sample Desired Data:
id email name emailFromTable2 emailstatus
1 test2@yahoo.com lili test2@yahoo.com bounced
2 tesere@yahoo.com mike Null Null
3 tedfd2@yahoo.com nik tedfd2@yahoo.com bounced
4 tdfdft2@yahoo.com sam Null Null
5 tedft2@yahoo.com james tedft2@yahoo.com bounced
6 tedft2@yahoo.com San Null
回答1:
It looks like your root question is:
"Find out whether every record in Applicant has ever had a bounced email."
The following query should get you your desired output (NULL values when not bounced, 'bounced' otherwise).
SELECT A.id, A.name, A.email, B.emailstatus
FROM Applicant A
LEFT OUTER JOIN
(
SELECT DISTINCT email, emailstatus
FROM tbl_webhook
) B
ON A.email = B.email
AND B.emailstatus = 'bounced'
Some Notes:
- Joining on a non id field is fine. The only thing you might need to consider is performance (as id fields tend to be either the primary key or part of the primary key). I wouldn't worry too much about this, unless you notice that its causing a problem. Introducing an index on email for both tables would help if it turns out to be a problem.
- Using a LEFT OUTER JOIN with B.emailstatus = 'bounced' ensures that only rows where emailstatus is bounced are included in the join (meaning even though john@test.com has an email status, he still shows up as NULL in the result set, because his status isn't 'bounced').
- SQL Fiddle (link below) is a fantastic way of communicating SQL problems to people over the internet.
- Use DISTINCT to remove identical rows. This will stop you from getting multiple identical records as a result of the multiple bounced emails records in tbl_webhook.
SQL Fiddle Schema:
CREATE TABLE Applicant (id int, name varchar(10), email varchar(100))
INSERT INTO Applicant VALUES(1, 'John', 'john@test.com')
INSERT INTO Applicant VALUES(2, 'Bob', 'bob@test.com')
INSERT INTO Applicant VALUES(3, 'Mary', 'mary@test.com')
INSERT INTO Applicant VALUES(4, 'Jane', 'jane@test.com')
CREATE TABLE tbl_Webhook (id varchar(2), email varchar(100), emailstatus varchar(10))
INSERT INTO tbl_Webhook VALUES('AA', 'john@test.com', 'received')
INSERT INTO tbl_Webhook VALUES('BB', 'bob@test.com', 'bounced')
INSERT INTO tbl_Webhook VALUES('CC', 'mary@test.com', 'sent')
回答2:
Move the H.[EmailStatus] = 'bounced' OR H.[EmailStatus] IS NULL
to the WHERE clause. This should give you the desired result.
In OUTER JOIN
s join condition is not the same as the filter condition in the WHERE
clause
EDIT: Updated the condition so that rows without a status get pulled into the result set.
来源:https://stackoverflow.com/questions/20751848/what-kind-of-join-between-2-sql-table-that-they-dont-have-common-id