简体   繁体   中英

UNION or JOIN for SELECT from multiple tables

My Issue

I am trying to select one row from multiple tables based on parameters, but my limited knowledge of SQL joining is holding me back. Could somebody possibly point me in the right direction?

Consider these table structures:

+-----------------------+     +---------------------+
| Customers             |     | Sellers             |
+-------------+---------+     +-----------+---------+
| Customer_ID | Warning |     | Seller_ID | Warning |
+-------------+---------+     +-----------+---------+
| 00001       | Test 1  |     | 00008     | Testing |
| 00002       | Test 2  |     | 00010     | Testing |
+-------------+---------+     +-----------+---------+

What I would like to do is one SELECT to retrieve only one row, and in this row will be the 'Warning' field for each of the tables based on the X_ID field.

Desired Results

So, if I submitted the following information, I would receive the following results:

Example 1:

Customer_ID = 00001
Seller_ID = 00008

Results:
+-----------------------------------+
| Customer_Warning | Seller_Warning |
+------------------+----------------+
| Test 1           | Testing        |
+------------------+----------------+

Example 2:

Customer_ID = 00001
Seller_ID = 00200

Results:
+-----------------------------------+
| Customer_Warning | Seller_Warning |
+------------------+----------------+
| Test 1           | NULL           |
+------------------+----------------+

What I Have Tried

This is my current code (I am receiving loads of rows):

SELECT c.Warning 'Customer_Warning', s.Warning AS 'Seller_Warning'
FROM Customers c,Sellers s
WHERE c.Customer_ID = @Customer_ID
    OR s.Seller_ID = @Seller_ID

But I have also played around with UNION , UNION ALL and JOIN . Which method should I go for?

Since you're not really joining tables together, just selecting a single row from each, you could do this:

SELECT 
    (SELECT Warning 
     FROM Customers 
     WHERE Customer_ID = @Customer_ID) AS Customer_Warning,
    (SELECT Warning 
     FROM Sellers 
     WHERE Seller_ID = @Seller_ID) AS Seller_Warning

The problem is you're getting a cartesian product of rows in each table where either column has the value you're looking for.

I think you just want AND instead of OR :

SELECT c.Warning 'Customer_Warning', s.Warning AS 'Seller_Warning'
FROM Customers c 
JOIN Sellers s
ON c.Customer_ID = @Customer_ID
    AND s.Seller_ID = @Seller_ID

If performance isn't good enough you could join two filtered subqueries:

SELECT c.Warning 'Customer_Warning', s.Warning AS 'Seller_Warning'
FROM (SELECT Warnning FROM Customers WHERE c.Customer_ID = @Customer_ID) c,
     (SELECT Warning FROM Sellers s WHERE s.Seller_ID = @Seller_ID) s

But I suspect SQL will be able to optimize the filtered join just fine.

it wont return a row if one of the ID's doesnt exist.

Then you want a FULL OUTER JOIN :

SELECT c.Warning 'Customer_Warning', s.Warning AS 'Seller_Warning'
FROM Customers c 
FULL OUTER JOIN Sellers s
ON c.Customer_ID = @Customer_ID
    AND s.Seller_ID = @Seller_ID

The problem that you are facing is that when one of the tables has no rows, you are going to get no rows out.

I would suggest solving this with a full outer join :

SELECT c.Warning as Customer_Warning, s.Warning AS Seller_Warning
FROM Customers c FULL OUTER JOIN
     Sellers s
     ON c.Customer_ID = @Customer_ID AND s.Seller_ID = @Seller_ID;

Also, I strongly discourage you from using single quotes for column aliases. Use single quotes only for string and date constants. Using them for column names can lead to confusion. In this case, you don't need delimiters on the names at all.

What I have seen so far here are working examples for your scenario. However, there is no real sense behind putting unrelated data together in one row. I would propose using a UNION and separate the values in your code:

SELECT 'C' AS Type, c.Warning
FROM Customers c
WHERE c.Customer_ID = @Customer_ID
UNION
SELECT 'S' AS Type, s.Warning
FROM Sellers s
WHERE s.Seller_ID = @Seller_ID

You can use the flag to distinguish the warnings in your code. This will be more efficient then joining or sub queries and will be easy to understand later on (when refactoring). I know this is not 100% what you ask for in your question but that's why I challenge the question :)

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM