I am trying to write a report that at first glance seemed fairly straightforward. However, after numerous attempts, I am struggling to find an approach that works. We have about 350K records in VendTable, but vendors are duplicated across 26 companies so in reality there ~13K UNIQUE vendor accounts.
I am trying to write a report that returns any vendor that has not had a PO, Invoice and Payment (PurchTable, VendInvoiceJour and VendTable respectively) since a certain date.
The complex part (for me) is, all the keys contain dataareaid, but I want my query to run independently of that. I don't mean crossCompany, because that would return (up to) 26 records for a single Vendor (since it exists 26 times in the database). To be clear, if vendor A has a PO in ANY company, I don't want vendor A returned in my resultset AT ALL.
I have tried doing this using the query below (the +'' on the AccountNum tricks the AOT so the resulting sql query drops dataareaid from the subquery) but the resulting SQL was NESTED "NOT (EXIST" so the NOTs cancel out causing unexpected and incorrect results.
X++ Code
while select crossCompany AccountNum, InvoiceAccount, NBDCMMSAllowInvoices, VendGroup, Party
from vendTable
group by AccountNum, InvoiceAccount, Party, VendGroup, NBDCMMSAllowInvoices
where vendTable.Blocked != CustVendorBlocked::All
notExists join * from purchTable WHERE
purchTable.OrderAccount == vendTable.AccountNum+''
&& purchTable.createdDateTime > cutoffDate
notExists join * from vendTrans
where vendTrans.AccountNum == vendTable.accountNum+''
&& vendTrans.TransDate > cutoffDateTrans
notExists join * from vendInvoiceJour
where vendInvoiceJour.InvoiceAccount == vendTable.accountNum+''
&& vendInvoiceJour.InvoiceDate > cutoffDateTrans
Resulting SQL:
SELECT T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.NBDCMMSALLOWINVOICES,T1.VENDGROUP,T1.PARTY,T1.DATAAREAID,T1.RECID
FROM VENDTABLE T1 WHERE ((T1.PARTITION = PartitionID) AND (T1.BLOCKED <> 2))
AND NOT (EXISTS (SELECT 'x' FROM PURCHTABLE T2 WHERE
((T2.PARTITION = PartitionID) AND ((T2.ORDERACCOUNT=T1.ACCOUNTNUM AND (T2.DATAAREAID = T1.DATAAREAID) AND (T2.PARTITION = T1.PARTITION)) AND (T2.CREATEDDATETIME>?)))
AND NOT (EXISTS (SELECT 'x' FROM VENDTRANS T3 WHERE
((T3.PARTITION = PartitionID) AND ((T3.ACCOUNTNUM=T1.ACCOUNTNUM AND (T3.DATAAREAID = T1.DATAAREAID) AND (T3.PARTITION = T1.PARTITION)) AND (T3.TRANSDATE>?)))
AND NOT (EXISTS (SELECT 'x' FROM VENDINVOICEJOUR T4 WHERE
((T4.PARTITION = PartitionID) AND ((T4.INVOICEACCOUNT=T1.ACCOUNTNUM AND (T4.DATAAREAID = T1.DATAAREAID) AND (T4.PARTITION = T1.PARTITION)) AND (T4.INVOICEDATE>?)))
)
)
)
)
)
) GROUP BY T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.NBDCMMSALLOWINVOICES,T1.VENDGROUP,T1.PARTY ORDER BY T1.ACCOUNTNUM,T1.INVOICEACCOUNT,T1.NBDCMMSALLOWINVOICES,T1.VENDGROUP,T1.PARTY
Those nested NOT EXIST join are causing me grief. Is there some way around this, or perhaps a completely different approach?
I suppose you can't use a query?
Query q;
QueryBuildDataSource qbdsVendTable;
QueryBuildDataSource qbds;
QueryRun qr;
q = new Query();
q.allowCrossCompany(true);
qbdsVendTable = q.addDataSource(tableNum(VendTable));
qbdsVendTable.addSelectionField(fieldNum(VendTable, AccountNum));
qbdsVendTable.addSelectionField(fieldNum(VendTable, InvoiceAccount));
qbdsVendTable.addSelectionField(fieldNum(VendTable, NBDCMMSAllowInvoices));
qbdsVendTable.addSelectionField(fieldNum(VendTable, VendGroup));
qbdsVendTable.addSelectionField(fieldNum(VendTable, Party));
qbdsVendTable.addGroupByField(fieldNum(VendTable, AccountNum));
qbdsVendTable.addGroupByField(fieldNum(VendTable, InvoiceAccount));
qbdsVendTable.addGroupByField(fieldNum(VendTable, NBDCMMSAllowInvoices));
qbdsVendTable.addGroupByField(fieldNum(VendTable, VendGroup));
qbdsVendTable.addGroupByField(fieldNum(VendTable, Party));
qbdsVendTable.addRange(fieldNum(vendTable, Blocked)).value(SysQuery::valueNot(CustVendorBlocked::All));
qbds = qbdsVendTable.addDataSource(tableNum(PurchTable));
qbds.joinMode(JoinMode::NoExistsJoin);
qbds.addLink(fieldNum(VendTable, AccountNum), fieldNum(PurchTable, OrderAccount));
qbds.addRange(fieldNum(PurchTable, CreatedDateTime)).value('>'+queryValue(cutoffDate));
qbds = qbdsVendTable.addDataSource(tableNum(VendTrans));
qbds.joinMode(JoinMode::NoExistsJoin);
qbds.addLink(fieldNum(VendTable, AccountNum), fieldNum(VendTrans, AccountNum));
qbds.addRange(fieldNum(VendTrans, TransDate)).value('>'+queryValue(cutoffDateTrans));
qbds = qbdsVendTable.addDataSource(tableNum(VendInvoiceJour));
qbds.joinMode(JoinMode::NoExistsJoin);
qbds.addLink(fieldNum(VendTable, AccountNum), fieldNum(VendInvoiceJour, InvoiceAccount));
qbds.addRange(fieldNum(VendInvoiceJour, InvoiceDate)).value('>'+queryValue(cutoffDateTrans));
qr = new QueryRun(q);
while (qr.next())
{
vendTable = qr.get(tableNum(vendTable));
//and so on
}
If not then just create a view based on a union query and use it in your report. You can use VendTable as a parent datasource, ie VendTable join PurchTable, VendTable join VendTrans, and VendTable join VendInvoiceJour in a union, or decide to use a different union structure eg no VendTable and only specific fields from the other 3 tables. You can use computed columns if necessary. Then just select records from VendTable notExists join your new view.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.