如何在SQL Server子查询中添加日期范围过滤器并修正报表数据异常
问题分析与解决方案
问题出在你的左连接逻辑和sum计算的范围上——虽然你在收款单(ODPI)的子查询里限制了日期,但左连接意味着即使收款日期不在2019年,只要销售订单符合条件,关联的DPI1(税明细)记录依然会被纳入sum计算,最终导致不该出现的fbdwnp without vat数据被统计进来。
下面给出两种针对性的解决方案,你可以根据业务需求选择:
方案1:保留订单但仅统计合规收款的税明细数据
如果你需要保留销售日期在2019年的所有订单,但仅当收款日期也在2019年时才计算fbdwnp without vat,可以修改sum表达式,添加对收款日期的判断:
select a.DocDate as 'Order Date', f.DocDate as 'Collection Date', b.LineTotal as 'fbsales amount', a.SlpCode, a.CardCode, b.DocEntry, -- 修改sum逻辑,仅统计收款日期在2019年的税明细 sum( case when f.DocDate is not null -- 确保对应的收款单在目标日期范围内 then case when e.TaxCode = 'NBT2' then cast(e.LineTotal as decimal(22,8)) /1.02 when e.TaxCode = 'N2+V15' then (cast(e.LineTotal as decimal(22,8)) /1.173) when e.TaxCode = 'VAT8' then (cast(e.LineTotal as decimal(22,8)) /1.08) else e.LineTotal end else 0 -- 收款日期不在范围内时,该字段显示为0 end ) as 'fbdwnp without vat', b.LineNum from ORDR a left join RDR1 b on b.DocEntry = a.DocEntry left join OSLP c on c.SlpCode = a.SlpCode left join OITM d on d.ItemCode = b.ItemCode left Join (select TaxCode,LineTotal,BaseEntry,BaseLine,DocEntry from DPI1 where [TargetType]<>'14') e on e.BaseEntry = b.DocEntry and e.BaseLine = b.LineNum left Join (select DocEntry,DocDate From ODPI where CANCELED = 'N' and DocDate between '20190101' and '20191231') f on f.DocEntry = e.DocEntry where a.CANCELED = 'N' and d.U_Product_Type = 'Facebook' and a.DocDate between '20190101' and '20191231' and a.SlpCode = 68 group by c.SlpName,a.SlpCode,b.LineTotal,d.DocEntry,a.CardCode,c.SlpName,b.DocEntry,a.DocDate,b.LineNum,f.DocDate
这样,当收款日期为2020-01-09时,f.DocDate会因为子查询的过滤而变为NULL,对应的税明细不会被计入sum,最终fbdwnp without vat会显示为0,符合你只展示fbsales amount的需求。
方案2:直接过滤掉收款日期不合规的订单
如果你不需要保留收款日期不在2019年的销售订单,可以选择以下两种方式之一:
方式A:将左连接收款单改为内连接
-- 把left Join改成inner Join,只保留有合规收款记录的订单 inner Join (select DocEntry,DocDate From ODPI where CANCELED = 'N' and DocDate between '20190101' and '20191231') f on f.DocEntry = e.DocEntry
方式B:在where条件中添加收款日期校验
在where子句末尾追加:
and f.DocDate is not null
这两种方式都会直接过滤掉收款日期不在2019年的订单,报表中只会显示销售和收款都在2019年的记录。
额外优化建议
- 你的
group by子句包含了c.SlpName,但select中没有输出该字段,这可能触发SQL语法错误(取决于数据库模式),建议要么在select中添加c.SlpName,要么从group by中移除该字段。 - 日期条件尽量使用标准格式(如
'2019-01-01'),避免数据库解析日期时出现异常。
内容的提问来源于stack exchange,提问作者Kith
相关产品推荐
相关产品推荐

