基于 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"。 这是我不明白的地方。
如果仅在这一点上能得到一些帮助,它就会解决我的问题,我会接受这个答案。然而...
奖金回合
以上都很好,但如果可以的话,我会接受这个作为高于其他答案的答案。
我可以连接产品名称吗?我一直在看 COALESCE
和 FOR 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
首先,很抱歉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"。 这是我不明白的地方。
如果仅在这一点上能得到一些帮助,它就会解决我的问题,我会接受这个答案。然而...
奖金回合
以上都很好,但如果可以的话,我会接受这个作为高于其他答案的答案。
我可以连接产品名称吗?我一直在看 COALESCE
和 FOR 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