基于 CASE 的 3 个表之间的 LEFT JOIN 有条件地 return 值

Conditionally return values from LEFT JOIN between 3 tables based on CASE

首先,很抱歉post。它真的比看起来更简单;-)

我正在尝试做一些我认为在概念上很简单的事情,而且我相信我已经完成了大部分工作,但还有最后一部分我无法在没有错误的情况下实现,我无法理解解决方法。

我有三个相关的 tables。

订单:
每一行都是一个具有唯一 ID 的订单,绝不会重复。

+---------+---------+
| OrderID | Name    |
+---------+---------+
| 1       | Order 1 |
| 2       | Order 2 |
| 3       | Order 3 |
+---------+---------+

订单详情:
关系型 table,其中每一行都是订单上的一条产品线。

+---------+-----------+
| OrderID | ProductID |
+---------+-----------+
| 1       | a         |
| 2       | b         |
| 2       | c         |
| 3       | a         |
| 3       | b         |
| 3       | b         |
+---------+-----------+

如您所见,有些订单只有一个产品 (1),有些订单有多个产品 (2),有些订单有重复产品 (3)。

产品
每一行都是一个具有唯一ID的产品,绝不会重复。

+-----------+-------------+
| ProductID | Description |
+-----------+-------------+
| a         | Chicken     |
| b         | Fish        |
| c         | Beef        |
+-----------+-------------+

我想 return 订单中的所有行 table 并且有条件地 return 一列中有关相关产品的一些信息。

条件是我看每个订单有多少DISTINCT个商品。如果它只是 1,那么我想 return 产品描述值。如果它超过 1 那么我想 return 一些占位符文本,例如 'Multi'.

我想我需要使用 CASE 来让它工作,但我想不出来。

我可以像这样成功计算唯一产品:

SELECT 
    o.Name
   ,COUNT(DISTINCT d.ProductId) as 'Unique Products'
FROM Orders o

LEFT JOIN OrderDetails d ON o.OrderID = d.OrderID
LEFT JOIN Products p on d.ProductId = p.ProductId

GROUP BY o.Name
ORDER BY o.Name DESC

GO

结果是这样的:

+---------+-----------------+
| Name    | Unique Products |
+---------+-----------------+
| Order 1 | 1               |
| Order 2 | 2               |
| Order 3 | 2               |
+---------+-----------------+

我要的是这个:

+---------+-----------------+
| Name    | Unique Products |
+---------+-----------------+
| Order 1 | Chicken         |
| Order 2 | Multi           |
| Order 3 | Multi           |
+---------+-----------------+

我一直在尝试使用 CASE,我相信我是正确的:

CASE WHEN (COUNT(DISTINCT d.ProductId)) > 1 THEN 'Multi' ELSE p.Description END AS 'Products'

但是,除非我将 p.Description 添加到 GROUP BY 然后我得到错误(我理解):

Column 'Product.Description' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

但是如果我添加它,结果不是我想要的,例如:

+---------+----------+
| Name    | Products |
+---------+----------+
| Order 1 | Chicken  |
| Order 2 | Fish     |
| Order 2 | Beef     |
| Order 3 | Chicken  |
| Order 3 | Fish     |
| Order 3 | Fish     |
+---------+----------+
例如,

什么时候它应该只在一行上说 "Order 2 - Multi"。 这是我不明白的地方

如果仅在这一点上能得到一些帮助,它就会解决我的问题,我会接受这个答案。然而...

奖金回合

以上都很好,但如果可以的话,我会接受这个作为高于其他答案的答案。

我可以连接产品名称吗?我一直在看 COALESCEFOR XML PATH,但我根本无法理解它们,所以我什至没有任何代码可以展示。

结果看起来像这样:

+---------+--------------+
| Name    | Products     |
+---------+--------------+
| Order 1 | Chicken      |
| Order 2 | Fish;Beef    |
| Order 3 | Chicken;Fish |
+---------+--------------+

如果你做到了这一步,我会表扬你!谢谢!

你很接近。您只需要一些 case 逻辑和围绕描述的聚合函数:

SELECT o.Name,
       (CASE WHEN COUNT(DISTINCT d.ProductId)  = 1
             THEN MAX(p.description)
             ELSE 'Multi'
        END) as Descriptions
FROM Orders o LEFT JOIN
     OrderDetails d
     ON o.OrderID = d.OrderID LEFT JOIN
     Products p
     ON d.ProductId = p.ProductId
GROUP BY o.Name
ORDER BY o.Name DESC

第二部分是一个非常不同的问题。在 SQL 服务器中,您需要使用 XML 子查询:

select o.Name,
       stuff((select distinct ',' + p.description
              from OrderDetails d left join
                   Products p
                   on d.ProductId = p.ProductId
              where o.OrderID = d.OrderID 
              for xml path (''), type
             ).value('.', 'nvarchar(max)'
                    ), 1, 1, ''
            ) as descriptions
from Orders o
order by o.Name desc