根据CASE

时间:2015-09-21 11:40:07

标签: sql sql-server-2008 left-join case

首先,为长篇帖子道歉。它看起来真的很简单; - )

我正在尝试做一些我认为在概念上很简单的事情,而且我相信我在那里的大部分方式,但最后一部分是我无法实现而没有错误,我无法弄清楚如何修复。

我有三张相关的表格。

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

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

订单明细:
关系表,其中每一行都是订单上的产品系列。

+---------+-----------+
| 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        |
+-----------+-------------+

我想从Orders表中返回所有行,并在一列中有条件地返回有关相关产品的一些信息。

条件是我查看每个订单有多少DISTINCT个产品。如果它只是1,那么我想返回产品描述值。如果它超过1,那么我想返回一些占位符文本,例如“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,否则我会收到错误(我理解):

  

列'Product.Description'在选择列表中无效,因为它不包含在聚合函数或GROUP BY子句中。

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

+---------+----------+
| 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 |
+---------+--------------+

如果你已经做到这一点,我推荐你!谢谢!

1 个答案:

答案 0 :(得分:5)

你非常接近。您只需要一些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 Server中,您需要使用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