按子查询的结果分组 - SQL Server

时间:2016-03-11 19:16:31

标签: sql-server tsql sql-server-2008-r2

长期用户,第一次海报。

这是一个关于使用子查询的结果来聚合计数的问题。我完全愿意改变我的方法,但我想确保没有一件容易的事情我先失踪了。

假设我有一个包含这些列的订单表:

Order_Id
Order_Datetime
Order_Type
Order_Status

我创建了一个索引视图来支持最常用的读访问:

CREATE VIEW vw_OrdersByDate WITH SCHEMABINDING AS
SELECT CONVERT(varchar(10), Order_Datetime, 121) AS Order_Date,
       Order_Type,
       Order_Status,
       COUNT_BIG(*)
  FROM Orders
 GROUP BY CONVERT(varchar(10), Order_Datetime, 121), Order_Type, Order_Status;

CREATE UNIQUE CLUSTERED INDEX vw_OrdersByDate_main_idx ON
       (Order_Date, Order_Type, Order_Status);

到目前为止,这么好。在阅读报告时(使用(noexpand)),它会在~50M订单中快速执行盲注。然而,现在我们已经推出了一种改变行业的产品,每个管理人员都需要逐个了解产品的运行方式。

我们有一个OrderLines子表,其中包含以下列:

OrderLine_Id
Order_Id
Product_Id 

这就是问题所在,我希望在原始视图中添加一列,以便我可以按包含超级产品的订单和不包含超级产品的订单进行过滤。类似的东西:

CREATE VIEW vw_OrdersByDate WITH SCHEMABINDING AS
SELECT CONVERT(varchar(10), Order_Datetime, 121) AS Order_Date,
       Order_Type,
       Order_Status,
       CASE WHEN EXISTS (SELECT 1 FROM OrderLines OL 
                          WHERE OL.Order_Id = O.Order_Id 
                            AND Product_Id = 123) THEN 1
            ELSE 0
       END AS Super_Product_Exists,
       COUNT_BIG(*)
  FROM Orders O
 GROUP BY CONVERT(varchar(10), Order_Datetime, 121), Order_Type,
          Order_Status, Super_Product_Exists;

但我做不到。我已经尝试将整个CASE语句放在GROUP BY子句中,并且“不能使用聚合或子查询...按列表...”。我不能使用LEFT JOIN / NULL,因为您无法在具有任何外部联接的视图上创建索引。

我觉得我错过了一些简单的东西,但无法弄明白(谷歌也不能......至少在我的搜索技能范围内)。

任何帮助都会非常感激,就像我之前说过的那样,我对完全不同的策略持开放态度,尽管我没有足够的自由来改变现有的事务数据结构......

谢谢!

2 个答案:

答案 0 :(得分:0)

您需要使用外部查询中的列加入EXISTS,这意味着您必须在EXISTS中公开这些列:

SELECT CONVERT(varchar(10), Order_Datetime, 121) AS Order_Date,
       Order_Type,
       Order_Status,
       CASE WHEN EXISTS (SELECT 1 FROM OrderLines OL 
                         INNER JOIN Orders OLO                 
                          ON OL.Order_Id = OLO.Order_Id 
                         WHERE OLO.OrderType=O.OrderType
                         AND OLO.Order_Status=O.Order_Status
                            AND OL.Product_Id = 123) THEN 1
            ELSE 0
       END AS Super_Product_Exists,
       COUNT_BIG(*)
  FROM Orders O
 GROUP BY CONVERT(varchar(10), Order_Datetime, 121), Order_Type,
          Order_Status;

答案 1 :(得分:0)

假设您想要查看所有产品并突出显示超级产品,我添加了一个基于product_id = 123的计算字段,名为superproduct,其值为yes或no。

SELECT CONVERT(varchar(10),Orders.Order_datetime, 121) AS Order_Date, 
Orders.order_type, 
Orders.order_status,
OrderLines.Product_id, 
CASE WHEN OrderLines.product_id =123 
     THEN 'Yes' 
     ELSE'No' 
END AS SuperProduct, 
COUNT_BIG(*) AS CountBig
FROM Orders 
INNER JOIN OrderLines ON Orders.Order_id = OrderLines.Order_id
GROUP BY 
CONVERT(varchar(10), 
Orders.Order_datetime, 121), 
Orders.order_type, 
Orders.order_status, 
OrderLines.Product_id

Results