SQL服务器:显示不同的订单列表,并指出哪些订单包含特定产品

SQL Server : display distinct list of orders, and indicate which orders contain specific products

我有一个包含大量数据的 table,但是 table 中的相关数据看起来像这样:

订单 table:

+----------+-----------+---------------+
| OrderID  | Product   |    Date       |
+----------+-----------+---------------+
|    1     | Apple     |  01/01/2001   |
|    1     | Pear      |  01/01/2001   |
|    1     | Pear      |  01/01/2001   |
|    1     | Orange    |  01/01/2001   |
|    1     | Pineapple |  01/01/2001   |
|    2     | Cherry    |  02/02/2002   |
|    2     | Cherry    |  02/02/2002   |
|    3     | Orange    |  03/03/2003   |
|    3     | Apple     |  03/03/2003   |
|    3     | Cherry    |  03/03/2003   |
+----------+-----------+---------------+

我想查询 return 一个不同的订单列表,如果订单包含某些产品,则表明:

+----------+-----------+--------+-------+
| OrderID  |   Date    | Apple? | Pear? |
+----------+-----------+--------+-------+
|    1     |01/01/2001 |    X   |   X   |
|    2     |02/02/2002 |        |       |
|    3     |03/03/2003 |    X   |       |
+----------+-----------+--------+-------+

这里是我停下来决定寻求帮助的地方:

WITH CTEOrder AS
(
   SELECT
       OrderID, Product, Date,
       ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY OrderID ASC) AS OrderRN
   FROM 
       Orders
)
CTEApple as 
(
    SELECT
        OrderID, Product, Date,
        ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY OrderID ASC) AS AppleRN
    FROM 
        Orders
    WHERE 
        Product = 'Apple'
),
CTEPear
(
    SELECT
        OrderID, Product, Date,
        ROW_NUMBER() OVER (PARTITION BY OrderID ORDER BY OrderID ASC) AS PearRN
    FROM 
        Orders
    WHERE 
        Product = 'Pear'
)
SELECT
    o.OrderID, o.Product, o.Date,
    co.OrderRN, a.AppleRN, p.PearRN
FROM 
    Orders AS o
OUTER JOIN 
    CTEOrder AS co ON o.OrderID = co.Orderid
OUTER JOIN 
    CTEApple AS a ON o.OrderID = a.OrderID
OUTER JOIN 
    CTEPear AS p ON o.OrderID = p.OrderID
WHERE 
    (co.OrderRN IS NULL AND a.AppleRN IS NULL AND p.PearRN IS NULL
     OR co.OrderRN = 1 AND a.AppleRN IS NULL AND p.PearRN IS NULL
     OR co.OrderRN = 1 AND a.AppleRN = 1 AND p.PearRN IS NULL
     OR co.OrderRN = 1 AND a.AppleRN = 1 AND p.PearRN = 1
     OR co.OrderRN = 1 AND a.AppleRN IS NULL AND p.PearRN = 1
     OR co.OrderRN IS NULL AND a.AppleRN = 1 AND p.PearRN IS NULL
     OR co.OrderRN IS NULL AND a.AppleRN = 1 AND p.PearRN = 1
     OR co.OrderRN IS NULL AND a.AppleRN IS NULL AND p.PearRN = 1)

目前我的结果集很笨重,有大量重复。

我认为我正朝着错误的方向前进,但我不知道 SQL 服务器中还有哪些其他工具可供我按照我需要的方式切割这些数据。

感谢您的指导!

在 Nik Shenoy 的指导下,这是我的结果集:

+----------+-----------+----------------+
| OrderID  |    Date   | Apple? | Pear? |
+----------+-----------+----------------+
|    1     | 01/01/2001|    x   |  NULL |
|    1     | 01/01/2001|  NULL  |   x   | 
|    1     | 01/01/2001|  NULL  |   x   |
|    1     | 01/01/2001|  NULL  |  NULL |
|    1     | 01/01/2001|  NULL  |  NULL |
|    2     | 02/02/2002|  NULL  |  NULL |
|    2     | 02/02/2002|  NULL  |  NULL |
|    3     | 03/03/2003|  NULL  |  NULL |
|    3     | 03/03/2003|    x   |  NULL |
|    3     | 03/03/2003|  NULL  |  NULL |
+----------+-----------+----------------+

我的下一步是什么,每个订单只有 1 行:

+----------+-----------+--------+-------+
| OrderID  |   Date    | Apple? | Pear? |
+----------+-----------+--------+-------+
|    1     |01/01/2001 |    X   |   X   |
|    2     |02/02/2002 |        |       |
|    3     |03/03/2003 |    X   |       |
+----------+-----------+--------+-------+

如果您提前知道所有产品,可以使用Transact-SQL PIVOT 关系运算符按产品cross-tabulate 数据。如果您使用 MAX 或 COUNT,您只需将 non-NULL 或 non-ZERO 输出转换为 'x'

SELECT
    PivotData.OrderID
,   PivotData.OrderDate
,   CASE WHEN PivotData.Apple IS NULL THEN '' ELSE 'X' END AS [Apple?]
,   CASE WHEN PivotData.Pear IS NULL THEN '' ELSE 'X' END AS [Pear?]
,   CASE WHEN PivotData.Orange IS NULL THEN '' ELSE 'X' END AS [Orange?]
,   CASE WHEN PivotData.Pineapple IS NULL THEN '' ELSE 'X' END AS     [Pineapple?]
,   CASE WHEN PivotData.Cherry IS NULL THEN '' ELSE 'X' END AS [Cherry?]
FROM
    (SELECT OrderID, Product, OrderDate) AS [Order]
PIVOT   (MAX(Product) FOR Product IN ( [Apple], [Pear], [Orange], [Pineapple], [Cherry] )) AS PivotData

您可以只使用条件聚合:

select o.orderid, date,
       max(case when product = 'Apple' then 'X' end) as IsApple,
       max(case when product = 'Pear' then 'X' end) as IsPear
from orders o
group by o.orderid, date;