联合查询中的计算表达式(MS Access)

问题描述 投票:1回答:2

我创建了一个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
2个回答
0
投票

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

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);

0
投票

问题是,对于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语句,但仍会影响字段类型。

© www.soinside.com 2019 - 2024. All rights reserved.