T-SQL:使用一个表或另一个表进行单查询连接

Shi*_*ion 6 sql t-sql left-join

我的问题如下:假设你有三个不同的表(产品,票据和退货)

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

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

| ReturnId | ProductId | Amount |
===================================
| 1        | 1         | 50$    |
Run Code Online (Sandbox Code Playgroud)

SINGLE Query如何获得以下输出:

| Product-ID | Name | Type | Amount |
=====================================
| 1          | Car  | Bill | 100$   |
| 1          | Car  | Bill | 200$   |
| 1          | Car  | Ret  | 50$    |
Run Code Online (Sandbox Code Playgroud)

我正在尝试各种各样的联盟,不知何故,我无法理解这一点.我究竟做错了什么?我到目前为止找到的最接近的解决方案是这样的:

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
Run Code Online (Sandbox Code Playgroud)

有一件事对我来说非常重要:真正的场景查询要大得多,而且我不想复制/粘贴查询的整个逻辑,就像使用联盟时的情况一样.

Gar*_*thD 19

以下将根据需要工作,

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
Run Code Online (Sandbox Code Playgroud)

  • 只是为了澄清我在其他答案之后发布的原因是在子查询中执行联合会减少产品上的表扫描次数并使查询更有效.在这里,有3个表扫描和1个连接,而其他解决方案需要4个表扫描(产品两次)和2个连接. (2认同)

Ode*_*ded 6

你可以使用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
Run Code Online (Sandbox Code Playgroud)