用零替换空值/将虚拟值放入Access中的空表中

时间:2011-08-09 13:22:49

标签: sql ms-access

我正在尝试根据从CSV文件中解析的费用和信用表创建费用和信用报告。费用表和信用表看起来基本相同,只有一个字段不同,如下所示

BillingPeriod | ItemCode | ItemName | Charge(Credit) | IsAdjustment | AdjustmentDate | ReportTimestamp

要创建此报告,我会将费用和信用分组,并根据我的项目代码对其进行汇总。例如,我工作的一个查询总计所有结算月份的辅助费用

SELECT Charges.BillingPeriod, Sum(Charges.Charge) as SumOfCharge
FROM Charges
WHERE (Charges.ItemCode Between 1301 and 1380)
GROUP BY Charges.BillingPeriod;

这一切都很好,但是当找不到商品代码时会出现问题。我希望这些查询足够灵活,以便显示包含或不包含特定费用/信用额的摘要,因为您可能不会在一个月内收取费用,并且可能会在另一个月内向您收取费用。

有问题的查询不起作用:

SELECT Credits.BillingPeriod, Sum(Credits.Credit) AS SumOfCredit
FROM Credits
WHERE (((Credits.ItemCode)=2217 Or (Credits.ItemCode)=2218 Or (Credits.ItemCode)=2241 Or (Credits.ItemCode)=2245 Or (Credits.ItemCode)=2260))
GROUP BY Credits.BillingPeriod;

由于我们尚未记入这些特定项目代码,因此无法对它们进行求和,结果集为空表。如果出现这种情况,有没有办法可以返回空的结算周期和SumOfCredit的0?我尝试了Nz()函数,以及IIf(IsNull()),但这对我没有帮助。

任何帮助都将不胜感激。

编辑:我更改了查询,使其看起来像这样:

SELECT Charges.BillingPeriod, SUM(Charges.Charge) AS SumOfCharge
FROM Charges
WHERE (((Charges.ItemCode) Between 1900 And 1995))
GROUP BY Charges.BillingPeriod
UNION
SELECT BillingPeriod, 0
FROM Charges
WHERE NOT EXISTS ( SELECT * FROM Charges WHERE (Charges.ItemCode Between 1900 And 1995));

这样可行,但不会显示所有结算周期。例如,如果一个特定的商品代码收取2011年1月1日和2011年1月1日的费用,它将仅显示这两个记录。我希望它在表格中显示每个可应用的结算周期。收费月份收费,零收费。我尝试在查询的末尾添加第三个UNION,再次选择BillingPeriod,0,但是它添加了一个月的重复记录,这是我不想要的。再一次,任何帮助都会很棒。

1 个答案:

答案 0 :(得分:1)

首先,遵循“少代码好”的口头禅,将笨拙的OR减少为一个IN:

WHERE Credits.ItemCode in (2217, 2218, 2241, 2245, 2260)

接下来,与一个包含所有不存在的ItemCodes的表联合:

SELECT Credits.BillingPeriod, Sum(Credits.Credit) AS SumOfCredit
FROM Credits
WHERE Credits.ItemCode in (2217, 2218, 2241, 2245, 2260)
GROUP BY Credits.BillingPeriod
UNION
SELECT null, 0
WHERE NOT EXISTS (SELECT * FROM Credits
    WHERE Credits.ItemCode in (2217, 2218, 2241, 2245, 2260));

如果Access不允许FROM子句 - 如果它不从DUAL或其他一行结果集中选择(例如FROM SYSTABLES WHERE ID = 1或其他),我不会这样做