Microsoft Dynamics AX 外部联接不同于等效项 SQL

Microsoft Dynamics AX Outer Join different than equivalent SQL

我有以下 x++ 方法:

public void run()
{
    CustTable           ct;
    DirPartyTable       dir;
    DirAddressBookParty party;
    DirAddressBook      ab;
    int                 ctr = 0;
    ;  

     while
       select * from ct
         where ct.UT_AP_CustomerStatus == 1
       outer join * from dir
         where dir.RecId == ct.Party 
            && dir.Partition == ct.Partition
       outer join * from party
         where ct.Party == party.Party
       outer join * from ab
         where party.AddressBook == ab.RecId
            && ab.Name == ''
    {
        ctr++;
    }

    info(strFmt('Finished with %1 rows selected',ctr));
}

当这个 运行 时,它总是 returns 2,346 行,这是 CUTTABLE 中的行数。但是,当我在 SSMS 中 运行 下面的 SQL 时,它只有 returns 一行,就像它应该的那样!

SELECT *
  FROM [DYNAMICS_AX].[dbo].[CUSTTABLE] ct
       LEFT OUTER JOIN [DYNAMICS_AX].[dbo].[DIRPARTYTABLE] dir
                    ON dir.RECID = ct.PARTY
                   AND dir.PARTITION = ct.PARTITION
       LEFT OUTER JOIN [DYNAMICS_AX].[dbo].[DIRADDRESSBOOKPARTY] party
                    ON ct.PARTY = party.PARTY
       LEFT OUTER JOIN [DYNAMICS_AX].[dbo].[DIRADDRESSBOOK] ab
                    ON party.ADDRESSBOOK = ab.RECID
 WHERE ct.UT_AP_CUSTOMERSTATUS = 1
   AND ab.NAME IS NULL

谁能看出 x++ 查询与我的 SQL 语句有什么问题?

谢谢, 克雷格

有了你们所有的伟大 help/suggestions,我意识到需要改变的地方。首先,我的 SQL 返回一行 ab.NAME 为空的原因是因为没有找到任何内容的左连接将 NULLS 放入结果集中。那并向我展示了如何查找 x++ 生成的 SQL 也确实有帮助,并且我能够将 x++ 更改为以下以给我想要更新的单行:

while
     select ct
        where ct.UT_AP_CustomerStatus == 1
        notExists join party from party
        where ct.Party == party.Party

感谢您的帮助!

你的 X++ 和 SQL 语句的区别在于 ab.Name == ''ab.NAME IS NULL

还有一个区别就是where条件应该写在JOIN ... ON部分:

 LEFT OUTER JOIN [DYNAMICS_AX].[dbo].[DIRADDRESSBOOK] ab
   ON party.ADDRESSBOOK = ab.RECID
     AND ab.NAME = '' -- <-- ab.Name condition in JOIN part
 WHERE ct.UT_AP_CUSTOMERSTATUS = 1

您可以看到从 AX x++ 到 SQL 和 Trace Parser 的确切 SQL 语句。

另一种选择是使用 generateOnly(仅限 dev/research):

select generateonly * from custTable;
info(custTable.getSQLStatement());

在 AX 中,我希望您的查询能为您提供 UT_AP_CustomerStatus == 1.

的客户

ab.Name == '' 不会更改计数,因为 AX 查询只是 select 具有空白名称的 DirAddressBook。它被翻译成 SQL 中的 ON 子句。 如果你真的想使用外连接 and have this range go to where clause,那么你需要创建一个查询并使用 query filters, that is use addQueryFilter.

不知道您真正想要得到什么,但您可以尝试使用普通内部联接去除 outer。此外,您永远不想在 Partition 或 DataAreaId 上 select,因为系统会为您执行此操作。

格式化为 best practice

public void run()
{
    CustTable           ct;
    DirPartyTable       dir;
    DirAddressBookParty party;
    DirAddressBook      ab;
    int                 ctr = 0;
    while select ct
        where ct.UT_AP_CustomerStatus == 1
        join RecId from dir
        where dir.RecId == ct.Party
        join RecId from party
        where ct.Party == party.Party
        join RecId from ab
        where ab.RecId == party.AddressBook
           && ab.Name == ''
    {
        ctr++;
    }

    info(strFmt('Finished with %1 rows selected',ctr));
}