从2个表中获取内容?

I want a query to grab results from 2 different tables where a specific user has added the row. So my 2 tables look like this:

addresses

  • id
  • address
  • user_id

emails

  • id
  • email
  • user_id

So, I want to pull the content from both tables where the user_id row equals 1. For context, imagine each user can add multiple addresses and emails to the site and I want to grab them all to display on their profile pages.

So I tried this:

SELECT *  
  FROM addresses
  JOIN emails USING (user_id) 
 WHERE user_id = '1'

However this doesn't work - It either returns 2 of each row from the first table, or nothing at all. I also tried this:

SELECT * 
  FROM addresses, 
       emails 
 WHERE user_id = '1'

But this also returns nothing.

Simple Union Version:

Select user_id, address as details from addresses
where user_ID = 1
UNION 
Select user_id, email as details from emails
where user_ID = 1

Here is some quick reading on union: http://www.tizag.com/sqlTutorial/sqlunion.php

From Input

table1:                        table2

id  user_id  address           id    user_id   email
----------------------         ----------------------
1   1        Add1              1       1       Email1
2   1        Add2              2       1       Email2
3   2        Add3              3       2       Email3
4   2        Add4              4       3       Email4

The results will be

user_id     details
-----------------------
1           Add1
1           Add2
1           Email1
1           Email2

try

"SELECT * FROM table1 INNER JOIN table2 USING (user_id) WHERE user_id = '1'"

then try this one

SELECT address.table1 , email.table2 FROM table1 INNER JOIN table2 ON id.table1 ='1'
SELECT table1.*,table2.*
FROM table1 INNER JOIN 
     table2 ON table1.user_ID = table2.user_id
Where table1.user_id = 1

From Input

table1:                        table2

id  user_id  address           id    user_id   email
----------------------         ----------------------
1   1        Add1              1       1       Email1
2   1        Add2              2       1       Email2
3   2        Add3              3       2       Email3
4   2        Add4              4       3       Email4

Expected Output

id  user_id address    id      user_id email
----------------------------------------------
1   1       Add1       1       1       Email1
2   1       Add2       1       1       Email1
1   1       Add1       2       1       Email2
2   1       Add2       2       1       Email2

Here is a query using Cartesian Product

SELECT A.*,B.* FROM
(SELECT address FROM addresses WHERE user_id = 1) A,
(SELECT email FROM emails WHERE user_id = 1) B;

Here is a query using INNER JOIN

SELECT A.*,B.* FROM
(SELECT address FROM addresses WHERE user_id = 1) A
INNER JOIN
(SELECT email FROM emails WHERE user_id = 1) B
USING (user_id);

Both of these queries are refactored to bring one row each. There is no need to bring the entire dataset together before searching for user_id 1.

One thing to note: Please make user user_id is indexed in both tables:

ALTER TABLE addresses ADD INDEX (user_id);
ALTER TABLE emails    ADD INDEX (user_id);

Here is something else: If user_id 1 has mutliple addresses and/or multiple emails here is what those two queries should look like:

Cartesian Product for Multiple Addresses/Multiple Emails

SELECT A.*,B.* FROM
(SELECT GROUP_CONCAT(address) AddressList FROM addresses WHERE user_id = 1) A,
(SELECT GROUP_CONCAT(email) EmailList FROM emails WHERE user_id = 1) B;

INNER JOIN for Multiple Addresses/Multiple Emails

SELECT A.*,B.* FROM
(SELECT GROUP_CONCAT(address) AddressList FROM addresses WHERE user_id = 1) A
INNER JOIN
(SELECT GROUP_CONCAT(email) EmailList FROM emails WHERE user_id = 1) B
USING (user_id);

Give it a Try !!!

UPDATE 2011-08-29 11:52 EDT

Since There is no guarantee a user_id would have both an address and an email address at the same time. You would have to perform a LEFT JOIN instead of an INNER JOIN since LEFT JOIN would have to favor at least one of those entites existing rather than the INNER JOIN compelling one to have a user_id with both entities. Try one of these:

SELECT
    A.ListOfAddresses AddressList,
    IFNULL(B.ListOfEmails,'<No Email Address>') EmailList
FROM
    (SELECT GROUP_CONCAT(address) ListOfAddresses FROM addresses WHERE user_id = 1) A
    LEFT JOIN
    (SELECT GROUP_CONCAT(email) ListOfEmails FROM emails WHERE user_id = 1) B
USING (user_id);

or

SELECT
    IFNULL(B.ListOfAddresses,'<No Address>') AddressList,
    A.ListOfEmails EmailList
FROM
    (SELECT GROUP_CONCAT(email) ListOfEmails FROM emails WHERE user_id = 1) A
    LEFT JOIN
    (SELECT GROUP_CONCAT(address) ListOfAddresses FROM addresses WHERE user_id = 1) B
USING (user_id);

Based on comments below the question, the question actually appears to be about sorting rows from different tables based on common criteria.

Beside having separate SELECTs and performing the sort client-side, a database server can perform the sort for you, roughly like this:

SELECT *
FROM (
    SELECT
        id addresses_id,
        address address_addresses,
        NULL emails_id,
        NULL emails_email,
        time
    FROM
        addresses
    WHERE
        user_id = 1
    UNION ALL
    SELECT
        NULL addresses_id,
        NULL address_addresses,
        id emails_id,
        email emails_email,
        time
    FROM
        emails
    WHERE
        user_id = 1
)
ORDER BY
    time -- Column not mentioned in question.

NOTE: Some returned rows will have NULLs at the end (these are from the addresses table) and some in front (these are from the emails).

This UNION is rather ugly and will get uglier with each new table though...