-1

I have spent hours researching how to write the proper SQL for the following task, and finally I feel that I have to get some help as this is the most complex SQL query I have ever had to write :(

I am putting together an email list with all the email adresses that we have on our customers. I have two tables: one customer table that contains customer level information, and one contact person table that contains person level information. Most of the data is overlapping, so the same email adress will occure in both tables. But the email adress field can be empty in both tables, and I do not want to return any empty rows.

Users that buy in our physical store are often only registered in the customer level table, but users that buys online are always registered both in the customer level table and the person level table.

I want to create a full list where I get all email adresses, where all email adresses are unique, no email adresses are duplicates and no email adresses are null. Also I want to join in columns from the customer table when the data is retrieved from the person table (the zip code in my example below).

Customers

| CustomerID | Firstname | Lastname | Email              | Zipcode |
| 22         | Jeff      | Carson   | jeffcar@mail.com   | 81712   |
| 29         | John      | Doe      | null               | 51211   |
| 37         | Gina      | Andersen | null               | 21147   |
| 42         | Brad      | Cole     | brad@company.org   | 39261   |

Contact persons

| PersonID | CustomerID | Firstname | Lastname | Email              |
| 8712     | 22         | Jeff      | Carson   | null               |
| 8916     | 29         | Jane      | Doe      | jane@doe.net       |
| 8922     | 29         | Danny     | Doe      | null               |
| 9181     | 37         | Gina      | Andersen | gina@gmail.com     |
| 9515     | 37         | Ben       | Andersen | ben88@gmail.com    |

I want to join the tables to generate the following:

Final table

| PersonID | CustomerID | Firstname | Lastname | Email              | Zipcode |
| 8712     | 22         | Jeff      | Carson   | jeffcar@mail.com   | 81712   |
| 8916     | 29         | Jane      | Doe      | jane@doe.net       | 51211   |
| 9181     | 37         | Gina      | Andersen | gina@gmail.com     | 21147   |
| 9515     | 37         | Ben       | Andersen | ben88@gmail.com    | 21147   |
| null     | 42         | Brad      | Cole     | brad@company.org   | 39261   |

I guessed this would be a fairly common task to do, but I haven't found anyone with a similar question, so I put my trust in the expertise out there.

4

3 回答 3

2

This SQL will get you exactly the results table you were looking for. I've made a live demo you can play with here at SQLFiddle.

SELECT
    ContactPerson.PersonID, 
    Customer.CustomerID, 
    COALESCE(ContactPerson.FirstName, Customer.FirstName) AS FirstName,
    COALESCE(ContactPerson.LastName, Customer.LastName) AS LastName,
    COALESCE(ContactPerson.Email, Customer.Email) AS Email,
    Customer.ZipCode
FROM Customer
LEFT JOIN ContactPerson
    ON ContactPerson.CustomerID = Customer.CustomerID
WHERE COALESCE(ContactPerson.Email, Customer.Email) IS NOT NULL

Results (identical to your desired results):

| PersonID | CustomerID | FirstName | LastName | Email              | ZipCode |
| 8712     | 22         | Jeff      | Carson   | jeffcar@mail.com   | 81712   |
| 8916     | 29         | Jane      | Doe      | jane@doe.net       | 51211   |
| 9181     | 37         | Gina      | Andersen | gina@gmail.com     | 21147   |
| 9515     | 37         | Ben       | Andersen | ben88@gmail.com    | 21147   |
| NULL     | 42         | Brad      | Cole     | brad@company.org   | 39261   |

A quick explanation of some key points to aid understanding:

The query uses a LEFT JOIN to join the two tables together. JOINs are pretty common once you get into SQL problems like this. I won't go into an in-depth explanation here: now that you know what they are called you should have no trouble Googling for loads of info on them!

NB: COALESCE basically means 'the first one of these options which isn't null' (docs). So this query will grab their name and email address from ContactPerson IF POSSIBLE, otherwise from Customer. If NEITHER of these tables hold an email address, then the WHERE clause makes sure that record isn't included at all, as required.

于 2013-11-05T15:10:42.510 回答
1
select con.personid, 
       con.customerid, 
       con.firstname, 
       con.lastname, 
       coalesce(con.email, cus.email) email, 
       cus.zipcode
from contact_persons con
right join
customers cus
on con.customerid = cus.customerid
于 2013-11-05T14:57:48.560 回答
1

This will work:

SELECT b.PersonID
      ,a.CustomerID
      ,a.FirstName
      ,a.LastName
      ,COALESCE(a.Email,b.Email) AS Email
      ,a.ZipCode
FROM Customers a
LEFT JOIN Contact b
  ON a.CustomerID = b.CustomerID
WHERE COALESCE(a.Email, b.Email) IS NOT NULL

Demo: SQL Fiddle

于 2013-11-05T15:06:52.093 回答