Reputation: 329
I have the below x++ method:
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));
}
When this runs, it ALWAYS returns 2,346 rows, which is how many rows are in CUSTTABLE. However, when I run the below SQL in SSMS, it ONLY returns one row, like it should!
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
Can anyone see what's wrong with the x++ query vs. my SQL statement?
Thanks, Craig
With all of your great help/suggestions, I realized what needed to be changed. First off, the reason my SQL was returning one row with the ab.NAME is null, is because the left joins that didn't find anything was putting NULLS into the result set. That and showing me how to look up the SQL that x++ generates really helped as well, and I was able to change my x++ to below to give me the single row I was wanting to update:
while
select ct
where ct.UT_AP_CustomerStatus == 1
notExists join party from party
where ct.Party == party.Party
Thanks for your help!
Upvotes: 0
Views: 1782
Reputation: 18051
In AX I would expect your query to give you the customeres where UT_AP_CustomerStatus == 1
.
The ab.Name == ''
does not change the count as the AX query just selects the DirAddressBook
with blank names. It is translated to an ON clause in SQL.
If you really want to use outer join and have this range go to where clause, then you need to create a query and use query filters, that is use addQueryFilter.
Not knowing what you really want to get, but you could try to strip the outer
using a plain inner join. Also, you never want to select on Partition or DataAreaId as the system does that for you.
Formatted with best practice in mind:
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));
}
Upvotes: 1
Reputation: 7627
Difference between you r X++ and SQL statement is in ab.Name == ''
and ab.NAME IS NULL
.
Another difference is that where condition should be written in JOIN ... ON part:
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
You can see exact SQL statement from AX x++ to SQL with Trace Parser.
Another option is to use generateOnly
(dev/research only):
select generateonly * from custTable;
info(custTable.getSQLStatement());
Upvotes: 2