T-SQL: Single-Query Join с одной или другой таблицей - PullRequest
6 голосов
/ 27 января 2012

Моя проблема заключается в следующем: скажем, у вас есть три разные таблицы (продукты, счета и возвраты)

| ProductId | Name |
=====================
| 1         | Car  |

| BillId | ProductId | Amount |
=================================
| 1      | 1         | 100$   |
| 2      | 1         | 200$   |

| ReturnId | ProductId | Amount |
===================================
| 1        | 1         | 50$    |

Как будет выглядеть ОДИН запрос, чтобы получить следующий вывод:

| Product-ID | Name | Type | Amount |
=====================================
| 1          | Car  | Bill | 100$   |
| 1          | Car  | Bill | 200$   |
| 1          | Car  | Ret  | 50$    |

Я пытался со всеми видами Joins, и почему-то я не могу понять это.Что я делаю неправильно?Самое близкое решение, которое я нашел до сих пор, было примерно таким:

SELECT p.*,
       (CASE
           WHEN b.Amount IS NOT NULL THEN 'Bill'
           ELSE 'Ret'
       END) AS Type,
       COALESCE(b.Amount, r.Amount) AS Amount
FROM Products p
LEFT JOIN Bills b ON b.ProductId = p.ProductId
LEFT JOIN Returns r ON r.ProductId = p.ProductId

Для меня очень важно одно: настоящий сценарий-запрос НАМНОГО больше, и я не хочу копировать / вставлятьвся логика запроса там, как если бы это было в случае использования Union.

Ответы [ 5 ]

19 голосов
/ 27 января 2012

Ниже будет работать по мере необходимости,

SELECT  Products.*, 
        [Type], 
        Amount
FROM    Products
        INNER JOIN
        (   SELECT  ProductID, 'Bill' [Type], Amount
            FROM    Bills
            UNION ALL
            SELECT  ProductID, 'Ret' [Type], Amount
            FROM    Returns
        ) transactions
            ON transactions.ProductID = Products.ProductID
6 голосов
/ 27 января 2012

Вы можете использовать UNION:

SELECT p.*, 'Bill' as [Type], b.Amount
FROM Products p
  INNER JOIN Bills b
    ON b.ProductId = p.ProductId
UNION 
SELECT p.*, 'Ret' as [Type], r.Amount
FROM Products p
  INNER JOIN Returns r
    ON r.ProductId = p.ProductId
1 голос
/ 10 октября 2014

Если вам не нравится внешний вид вложенных подзапросов, вы можете взять отличное решение GarethD и преобразовать его в общее выражение таблицы (CTE)

WITH Transactions AS (
    SELECT ProductID, 'Bill' [Type], Amount FROM Bills
      UNION ALL
    SELECT ProductID, 'Ret'  [Type], Amount FROM Returns
)
SELECT  p.*,  [Type], Amount
FROM    Products p
JOIN    Transactions t
            ON t.ProductID = p.ProductID

Вот демонстрация в SqlFiddle

1 голос
/ 27 января 2012

Попробуйте запрос UNION - что-то вроде

SELECT *, 'bill' FROM 
dbo.product
INNER JOIN bills ON dbo.product.Product_Id = dbo.bills.product_id
UNION
SELECT *, 'return' FROM 
dbo.product
INNER JOIN dbo.returns ON dbo.product.Product_Id = dbo.returns.product_id
1 голос
/ 27 января 2012
SELECT *
(SELECT Products.ProductID,
        Products.Name,
        'Bill' as Type,
        Bills.Amount
FROM        Products INNER JOIN Bills
            on Products.ProductID = Bills.ProductID
UNION
SELECT  Products.ProductID,
        Products.Name,
        'Ret' as Type,
        Returns.Amount
FROM        Products INNER JOIN Returns
            on Products.ProductID = Returns.ProductID) as iTable
WHERE   iTable.ProductID = 1
...