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));
}
我有以下 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));
}