【问题标题】:Calculated expression in Union Query (MS Access)Union Query (MS Access) 中的计算表达式
【发布时间】:2018-02-28 20:48:40
【问题描述】:

我创建了一个UNION ALL 来加入销售数据的客户“同比”总计。当前月份和年份从用户那里获取并传递给查询,我得到客户列,今年销售额 (CY) 和去年销售额 (PY)。这一切都有效。

现在我想添加一个计算出的差异列。这是我在SELECT 语句中显示表达式的代码:

SELECT
   IIF(CY.Cust <> "", CY.Cust, PY.Cust) AS Cust,
   CY.CurSales AS CurSales,
   PY.PriSales AS PriSales,
   PY.PriSales - CY.CurSales AS Diff 
FROM
   (SELECT
         [Unique] AS Cust,
         SUM(Amount) AS CurSales 
      FROM
         Sales_Data 
      WHERE
         (Month <= Forms!SalesInput!MonthNum AND 
          [Sales_Data]![Year] = Forms!SalesInput!Year)
      GROUP BY
         [Unique]
   ) AS CY 

   LEFT OUTER JOIN
      (SELECT
            [Unique] AS Cust,
            SUM(Amount) AS PriSales 
         FROM
            Sales_Data 
         WHERE
            (Month <= Forms!SalesInput!MonthNum AND 
             [Sales_Data]![Year] = Forms!SalesInput!Year-1)
         GROUP BY
            [Unique]
      ) AS PY 
   ON (CY.Cust = PY.Cust) 

UNION ALL

SELECT
    IIF(CY.Cust <> "", CY.Cust, PY.Cust) AS Cust,
    CY.CurSales AS CurSales,
    PY.PriSales AS PriSales,
    PY.PriSales - CY.CurSales AS Diff 
FROM
   (SELECT
         [Unique] AS Cust,
         SUM(Amount) AS CurSales 
    FROM
        Sales_Data 
    WHERE
        (Month <= Forms!SalesInput!MonthNum AND 
         [Sales_Data]![Year] = Forms!SalesInput!Year)
     GROUP BY
        [Unique]
    ) AS CY 

    RIGHT OUTER JOIN
      (SELECT
           [Unique] AS Cust,
           SUM(Amount) AS PriSales 
       FROM
           Sales_Data 
       WHERE
           (Month <= Forms!SalesInput!MonthNum AND 
           [Sales_Data]![Year] = Forms!SalesInput!Year-1)
       GROUP BY
           [Unique]
      ) AS PY 
    ON (CY.Cust = PY.Cust) 

   WHERE
      (CY.Cust IS NULL AND PY.Cust IS NOT NULL);

除非PY.PriSales = 0CY.CurSales = 0,否则此方法有效。如果任一结果为空白/空/零,我不会从我的表达式中得到结果。我在这里寻找解决方案没有运气。谁能指出我错过了什么?我觉得它必须非常简单。

【问题讨论】:

    标签: sql ms-access union


    【解决方案1】:

    由于您似乎在 MS Access 中运行完整的外部联接,并且需要返回非 NULL Sales 列,因此请考虑在 @ 之前用 NZ() 包装每个 Amount 987654322@ 将确保至少返回零:

    SUM(NZ(Amount)) AS ...
    

    你甚至可以在顶层这样做

    NZ(PY.PriSales) - NZ(CY.CurSales) AS Diff 
    

    顺便说一句,考虑将您的聚合查询保存为存储查询(即视图)并在更大的联合查询中引用它们以获得更紧凑、可读的 SQL:

    SELECT
       IIF(CY.Cust <> '', CY.Cust, PY.Cust) AS Cust,
       CY.CurSales AS CurSales,
       PY.PriSales AS PriSales,
       NZ(PY.PriSales) - NZ(CY.CurSales) AS Diff 
    FROM qryCYAgg AS CY 
    LEFT JOIN qryPYAgg AS PY ON (CY.Cust = PY.Cust) 
    
    UNION ALL
    
    SELECT
        IIF(CY.Cust <> '', CY.Cust, PY.Cust) AS Cust,
        CY.CurSales AS CurSales,
        PY.PriSales AS PriSales,
        NZ(PY.PriSales) - NZ(CY.CurSales) AS Diff 
    FROM qryCYAgg AS CY 
    RIGHT JOIN qryPYAgg AS PY ON (CY.Cust = PY.Cust) 
    
    WHERE (CY.Cust IS NULL AND PY.Cust IS NOT NULL);
    

    【讨论】:

    • 这成功了。谢谢你(和每个人)帮助我解决这个问题。结果非常简单,我在工具包中添加了一个新工具。
    • 太棒了!乐意效劳。我们都在那里敲着头撞墙,而一个简单的答案很容易获得。编码愉快!
    【解决方案2】:

    问题在于,对于UNION 查询,字段类型由顶部查询确定。如果只返回Null,那么你得到了错误的字段类型。

    您可以包含一个永远不会返回的标题行来设置标签和字段类型。

    SELECT "String field" As Cust, CDbl(1.1) As CurSales, CDbl(1.1) As PriSales, 1.1 As Diff
    FROM MSysObjects
    WHERE FALSE
    UNION ALL
    ... your unadjusted union query
    

    请注意,我假设这些销售的字段类型为 Double 类型。如果不是这样,您可以在标题中使用替代转换。

    Allen Browne 编写了一个替代的简单技巧来确保字段类型为here。它使用IIF 语句,该语句始终返回一个选项,但仍会影响字段类型。

    【讨论】:

    • 谢谢,这是有道理的,但是在进行此更改后我仍然遇到问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-15
    相关资源
    最近更新 更多