Dynamics AX中筛选指定天数内无全公司交易的供应商问题
问题分析
你的核心需求是:筛选出指定日期后,在所有26家公司中都没有采购订单、发票或付款记录的唯一供应商——也就是说,只要某个供应商在任意一家公司有符合条件的交易,就必须排除。
原代码的问题出在:你试图用vendTable.AccountNum+''来消除dataareaid的关联,但X++的crossCompany查询在生成NOT EXISTS子句时,会自动添加T2.DATAAREAID = T1.DATAAREAID的关联条件。这就导致子查询只检查当前供应商所在公司的交易,而不是所有公司的交易,完全违背了你的需求逻辑。
解决方案思路
我们需要调整查询逻辑,确保子查询跨所有公司检查交易记录,并且不与主表的dataareaid关联。这里提供两种可行的实现方式:
方式一:先收集所有有交易的供应商,再反向筛选
这种方式更直观,性能也更可控:先把所有在指定日期后有交易(采购/发票/付款)的供应商账号收集起来,再从唯一供应商列表中排除这些账号。
X++ 代码示例
Set vendWithTransactions = new Set(Types::String); cutoffDate = // 你的指定日期; cutoffDateTrans = // 你的交易日期阈值; // 1. 收集所有有采购订单的供应商账号 while select crossCompany distinct OrderAccount from purchTable where purchTable.createdDateTime > cutoffDate { vendWithTransactions.add(purchTable.OrderAccount); } // 2. 收集所有有付款记录的供应商账号 while select crossCompany distinct AccountNum from vendTrans where vendTrans.TransDate > cutoffDateTrans { vendWithTransactions.add(vendTrans.AccountNum); } // 3. 收集所有有发票记录的供应商账号 while select crossCompany distinct InvoiceAccount from vendInvoiceJour where vendInvoiceJour.InvoiceDate > cutoffDateTrans { vendWithTransactions.add(vendInvoiceJour.InvoiceAccount); } // 4. 筛选符合条件的唯一供应商 while select crossCompany AccountNum, InvoiceAccount, NBDCMMSAllowInvoices, VendGroup, Party from vendTable group by AccountNum, InvoiceAccount, Party, VendGroup, NBDCMMSAllowInvoices where vendTable.Blocked != CustVendorBlocked::All && !vendWithTransactions.in(vendTable.AccountNum) { // 处理结果,比如输出或存入临时表 info(strFmt('符合条件的供应商:%1', vendTable.AccountNum)); }
优势
- 逻辑清晰,容易调试
- 可以单独优化每个收集交易的子查询(比如添加合适的索引)
- 避免复杂的嵌套NOT EXISTS,减少SQL执行计划的不确定性
方式二:修正原查询,让NOT EXISTS子查询跨所有公司
如果想直接用单条查询实现,需要确保每个NOT EXISTS子查询都使用crossCompany,并且不关联主表的dataareaid。X++中可以通过显式指定子查询的crossCompany来实现:
X++ 代码示例
cutoffDate = // 你的指定日期; cutoffDateTrans = // 你的交易日期阈值; while select crossCompany AccountNum, InvoiceAccount, NBDCMMSAllowInvoices, VendGroup, Party from vendTable group by AccountNum, InvoiceAccount, Party, VendGroup, NBDCMMSAllowInvoices where vendTable.Blocked != CustVendorBlocked::All // 检查该供应商在所有公司都没有采购订单 not exists (select firstOnly 1 from purchTable crossCompany where purchTable.OrderAccount == vendTable.AccountNum && purchTable.createdDateTime > cutoffDate) // 检查该供应商在所有公司都没有付款记录 not exists (select firstOnly 1 from vendTrans crossCompany where vendTrans.AccountNum == vendTable.AccountNum && vendTrans.TransDate > cutoffDateTrans) // 检查该供应商在所有公司都没有发票记录 not exists (select firstOnly 1 from vendInvoiceJour crossCompany where vendInvoiceJour.InvoiceAccount == vendTable.AccountNum && vendInvoiceJour.InvoiceDate > cutoffDateTrans) { // 处理结果 info(strFmt('符合条件的供应商:%1', vendTable.AccountNum)); }
生成的SQL说明
修正后的SQL中,每个NOT EXISTS子查询都会跨所有公司查询,并且不会关联主表的dataareaid,逻辑变为:对于当前供应商账号,不存在任何公司的采购订单/付款/发票记录,完全符合你的需求。
性能优化建议
针对你的数据量(35万条VendTable,1.3万唯一供应商),建议:
- 确保以下字段有合适的索引:
PurchTable.OrderAccount+PurchTable.createdDateTimeVendTrans.AccountNum+VendTrans.TransDateVendInvoiceJour.InvoiceAccount+VendInvoiceJour.InvoiceDateVendTable.AccountNum+VendTable.Blocked
- 如果使用方式一,可以考虑用临时表替代
Set,当有大量交易供应商时,临时表的查询性能更稳定 - 测试时可以先限制日期范围,验证逻辑正确后再全量执行
内容的提问来源于stack exchange,提问作者Irfan jamal
相关产品推荐
相关产品推荐

