【问题标题】:Subtracting results from two queries / sub queries从两个查询/子查询中减去结果
【发布时间】:2019-11-07 03:45:38
【问题描述】:

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

目前我有一个表格,其中包含所有创建和取消的客户订单信息。每个客户订单都有唯一的订单号、销售地点、创建日期和取消日期。如果客户订单仍然有效,则取消日期将为空或“//”。如果客户订单被取消,那么它将有一个取消日期。作为一些附加信息,可以在 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 月份被取消,那么我想计算 3 月 15 日至 3 月的月份,从而结束1 月 10 日、2 月 5 日、3 月 12 日。

【问题讨论】:

  • CreationDateandCancelDate存储为字符串而不是日期/时间,因为它们可以包含`\`?

标签: sql tsql ms-access crosstab


【解决方案1】:

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

WHERE cust_ords.[CancelDate] = "" OR cust_ords.[CancelDate] = "//";

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

其次,在您的第二个查询中,您测试取消的订单,使用

WHERE cust_ords.[CancelDate] "" OR cust_ords.[CancelDate] "//";

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

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

所以你应该使用

WHERE 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 中是这样

【讨论】:

  • 你混淆了NzwithIsNullandFormat(Iif(缺少右括号。
  • 好吧,我知道我在测试客户订单是否被取消时做错了。另外作为一个小编辑我忘了提到我在 Microsoft Access 中使用 SQL。一个问题,即使在搜索之后也有点不清楚。对于使用 4 个参数的 codeiifcode 函数,或者更确切地说它如何使用它们,我有点困惑。这是codecust_ords.[CancelDate],'//'='//'code一个逻辑测试`?
  • @JimmyCricket:IIf最多只有 3 个参数,第四个属于Format(前面缺少括号)。代码应为:Format(IIf(Nz(cust_ords.[CancelDate],'//')='//', cust_ords.[CreationDate], cust_ords.[CancelDate]), 'MMMM yy')
【解决方案2】:

感谢@Søren Kongstad 的有用解释。我已相应地修改/更正了代码,以便为我提供所需的结果:

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 = CancelDate DatCreatCde = 创建日期

【讨论】:

    猜你喜欢
    • 2019-11-20
    • 2013-01-02
    • 2017-04-05
    • 1970-01-01
    • 1970-01-01
    • 2011-09-16
    • 1970-01-01
    • 2021-02-22
    • 2023-01-15
    相关资源
    最近更新 更多