从两个查询/子查询中减去结果

时间:2019-06-25 10:17:41

标签: sql tsql ms-access crosstab

我正在尝试创建一个查询,该查询返回客户订单的结果(在一个月内创建,例如一月)-该确切月份中已取消的客户订单(一月份的已取消客户订单)并显示按以下条件分组的结果位置(行)以及按年份和月份(列)。

当前,我有一个表,其中包含所有已创建和已取消的客户订单信息。每个客户订单都有唯一的订单号,出售位置,创建日期和取消日期。如果客户订单仍然有效,则取消日期将为null或“ //”。如果客户订单被取消,那么它将有一个取消日期。作为一些其他信息,可以在2019年1月创建客户订单,并在7月,8月或12月等时候取消客户订单。我想要获取的是通过执行一个月的总客户订单来获得所有月份的净客户订单-已取消的客户该月和特定位置的订单=该位置该月该月的净客户订单。

为了实现此目的,我尝试从表中创建两个单独的查询,第一个查询包含所有有效的客户订单,第二个查询包含所有取消。然后,我尝试在其他两个查询之间创建一个交叉表,尝试计算上面提到的内容,然后按位置分组,然后对年份和月份进行透视。

第一个查询,有效客户订单名为cust_valid(简体):

SELECT cust_ords.[SaleLoc], cust_ords.[OrderNum], cust_ords.[CreationDate], cust_ords.[CancelDate]
FROM cust_ords
WHERE cust_ords.[CancelDate] = "" OR  cust_ords.[CancelDate] = "//";

已取消名为cust_cancelled(简化)的客户订单的第二个查询:

SELECT cust_ords.[SaleLoc], cust_ords.[OrderNum], cust_ords.[CreationDate], cust_ords.[CancelDate]
FROM cust_ords
WHERE cust_ords.[CancelDate] <> "" OR  cust_ords.[CancelDate] <> "//";

最后,它们之间的交叉表:

TRANSFORM Count(cust_valid.[OrderNum]) AS [NetOrderCount]
SELECT cust_valid.[SaleLoc]
FROM cust_valid LEFT JOIN cust_cancelled ON cust_valid.[CreationDate] = cust_cancelled.[CancelDate]   
WHERE cust_valid.[CreationDate] = cust_cancelled.[CancelDate]
GROUP BY cust_ords.[SaleLoc]
PIVOT cust_valid.[CreationDate]; 

从这个意义上讲,我试图获取(计算)每个给定位置的净客户订单(一个月创建的总数-该月取消的订单),并显示每月结果(基本上列名称应为年和月)。因此,例如,如果我在1月有10个客户订单,2月有5个客户订单,3月有15个客户订单,如果1月的三个客户订单在3月被取消,那么我想算3月15日至3月,因此结束了与1月10日,2月5日,3月12日。

2 个答案:

答案 0 :(得分:0)

首先,您说如果取消日期为null或//,则订单有效,但是您要测试:

  

其中cust_ords。[CancelDate] =“”或cust_ords。[CancelDate] =“ //”;

要测试是否为空,请使用[CancelDate]为空,或将测试简化为ISNULL([CancelDate],'//')='//'

第二,在第二个查询中,使用

测试已取消的订单
  

在cust_ords。[CancelDate] <>“”或cust_ords。[CancelDate] <>“ //”;

这不是对已取消订单的测试否定!

 !(A or B) => !A and !B

所以您应该使用

  

在cust_ords。[CancelDate] <>“”和cust_ords。[CancelDate] <>“ //”;

或者是ISNULL(cust_ords。[CancelDate],'//')!='//'

由于查询本身,您正在按日期加入,即您在给定日期加入订单,而在同一日期取消。但是,您想查看订单和取消公关月。由于您取消了加入取消,因此您只会计算与订单在同一日期发生的取消!

SELECT
     cust_valid.[SaleLoc]
     ,  Format(
        iif(isnull(cust_ords.[CancelDate],'//')='//'
                ,cust_ords.[CreationDate]
                ,cust_ords.[CancelDate]
                ,'MMMM yy') Mnth
     , sum(iif(isnull(cust_ords.[CancelDate],'//'='//',1,0)) ValidOrders 
     , sum(iif(isnull(cust_ords.[CancelDate],'//'='//',0,1)) CancelledOrders 
     , sum(iif(isnull(cust_ords.[CancelDate],'//'='//',1,0))  
        - sum(iif(isnull(cust_ords.[CancelDate],'//'='//',0,1)) NetOrderCount 
FROM
       cust_ords
group by
     cust_valid.[SaleLoc]
     ,  Format(
        iif(isnull(cust_ords.[CancelDate],'//')='//'
                ,cust_ords.[CreationDate]
                ,cust_ords.[CancelDate]
                ,'MMMM yy')

这应该为您提供至少在SQL Server中对数据透视有用的基本数据

答案 1 :(得分:0)

感谢您@SørenKongstad的有用解释。我已经相应地修改/纠正了代码,以向我提供所需的结果:

SELECT CustOrders.[Grupp namn], Format(IIf(CustOrders.[DatAnnulCde]="/  /",CustOrders.[DatCreatCde],CustOrders.[DatAnnulCde]),"yyyy-mm") AS year_month, 
Sum(IIf(IsNull(CustOrders.DatCreatCde),0,1)) AS GrossOrders, Sum(IIf(CustOrders.DatAnnulCde<>"/  /",1,0)) AS CancelledOrders, 
Sum(IIf(IsNull(CustOrders.DatCreatCde),0,1)) - Sum(IIf(CustOrders.DatAnnulCde<>"/  /",1,0)) AS NetOrders
FROM CustOrders
WHERE CustOrders.[CarType] = "Renault PC" And CustOrders.[DatCreatCde] >= Format(Year(Now())&"-01-01","yyyy-mm-dd")
GROUP BY CustOrders.[Grupp namn], Format(IIf(CustOrders.[DatAnnulCde]="/  /",CustOrders.[DatCreatCde],CustOrders.[DatAnnulCde]),"yyyy-mm");

字段与初始示例中的名称不同 DatAnnulCde =取消日期 DatCreatCde = CreationDate