假设我们有两张表SalesOrder和SalesOrderLine,分别包含如下数据:
SalesOrderID (integer, primary key) |
DateAdded (date) |
---|---|
1 |
2010-01-01 |
2 |
2010-02-02 |
SalesOrderLineID (string, primary key) |
Quantity (integer) |
SalesOrderID (integer, foreign key) |
---|---|---|
AA |
32 |
1 |
BB |
67 |
1 |
CC |
66 |
1 |
SalesOrder为主表,SalesOrderLine为子表,通过SalesOrderId链接。
首先用X++的SELECT的OUTER JOIN来挑选纪录:
static void OuterJoinSelectJob3(Args _args) { SalesOrder recSalesOrder; SalesOrderLine recSalesOrderLine; struct struct4; ; struct4 = new struct ("int SalesOrderID;" + "date DateAdded;" + "str SalesOrderLineID;" + "int Quantity" ); while SELECT * from recSalesOrder OUTER JOIN recSalesOrderLine WHERE recSalesOrder.SalesOrderID == recSalesOrderLine.SalesOrderID && recSalesOrderLine.Quantity == 66 { struct4.value("SalesOrderID", recSalesOrder.SalesOrderID); struct4.value("DateAdded", recSalesOrder.DateAdded); struct4.value("SalesOrderLineID", recSalesOrderLine.SalesOrderLineID); struct4.value("Quantity", recSalesOrderLine.Quantity); info(struct4.toString()); } }
得到的结果是:
(SalesOrderID:1; DateAdded:2010/1/1; SalesOrderLineID:"CC"; Quantity:66) (SalesOrderID:2; DateAdded:2010/2/2; SalesOrderLineID:""; Quantity:0)
即数量等于66的SalesOrderLine对应的SalesOrder,还包含一个没有任何SalesOrderLine的SalesOrder。
类似的还可以使用Query在QueryBuildRange针对数量添加条件来获取纪录,在AOT创建Query QrySalesAndLines:
使用Query来获取纪录:
// X++ static void QueryBuildRange5rJob(Args _args) { Query query2; QueryBuildDataSource qbDataSource3; QueryRun queryRun4; QueryBuildRange qbRange6; SalesOrder recSalesOrder; SalesOrderLine recSalesOrderLine; struct struct5; ; struct5 = new struct ("int SalesOrderID;" + "date DateAdded;" + "str SalesOrderLineID;" + "int Quantity" ); query2 = new Query("QrySalesAndLines"); qbDataSource3 = query2.dataSourceName("SalesOrderLine_1"); // This QueryBuildRange restriction is in the ON clause of // the OUTER JOIN in the ANSI SQL Select statement that is // generated by the AOS for the underlying database system. qbRange6 = qbDataSource3.addRange (fieldNum(SalesOrderLine, Quantity)); qbRange6.value("66"); queryRun4 = new QueryRun(query2); while (queryRun4.next()) { recSalesOrder = queryRun4.getNo(1); recSalesOrderLine = queryRun4.getNo(2); struct5.value("SalesOrderID", recSalesOrder.SalesOrderID); struct5.value("DateAdded", recSalesOrder.DateAdded); struct5.value("SalesOrderLineID", recSalesOrderLine.SalesOrderLineID); struct5.value("Quantity", recSalesOrderLine.Quantity); info(struct5.toString()); } }
得到的结果和前面SELECT OUTER JOIN是一样的,SQL TRACE可以看到执行的SQL语句是:
-- ANSI SQL SELECT * from SalesOrder as tSO LEFT OUTER JOIN SalesOrderLine as tSOL ON (tSO.SalesOrderID = tSOL.SalesOrderID and tSOL.Quantity = 66 ) ;
注意这里的Quantity=66是作用在ON上的,即使子表中没有满足条件的纪录,主表也会包含在结果中,对应的子表字段使用子表字段的默认值填充,那么有办法过滤掉这些空值的左表纪录吗?在AX2012中新增了QueryFilter类,来看看它是如何运作的:
// X++ static void QueryFilter4fJob(Args _args) { Query query2; QueryBuildDataSource qbDataSource3; QueryRun queryRun4; // The QueryFilter class was not in Microsoft Dynamics AX 2009. QueryFilter qFilter7; SalesOrder recSalesOrder; SalesOrderLine recSalesOrderLine; struct struct5; struct5 = new struct ("int SalesOrderID;" + "date DateAdded;" + "str SalesOrderLineID;" + "int Quantity" ); query2 = new Query("QrySalesAndLines"); qbDataSource3 = query2.dataSourceName("SalesOrderLine_1"); // This QueryFilter restriction is in the WHERE clause of // the ANSI SQL Select statement that is generated by the AOS // for the underlying database system. qFilter7 = query2.addQueryFilter(qbDataSource3, "Quantity"); qFilter7.value("66"); queryRun4 = new QueryRun(query2); while (queryRun4.next()) { recSalesOrder = queryRun4.getNo(1); recSalesOrderLine = queryRun4.getNo(2); struct5.value("SalesOrderID", recSalesOrder.SalesOrderID); struct5.value("DateAdded", recSalesOrder.DateAdded); struct5.value("SalesOrderLineID", recSalesOrderLine.SalesOrderLineID); struct5.value("Quantity", recSalesOrderLine.Quantity); info(struct5.toString()); } }
得到的结果是:
(SalesOrderID:1; DateAdded:2010/1/1; SalesOrderLineID:"CC"; Quantity:66)
就只有quantity=66的SalesOrderLine对应的SalesOrder一条纪录了,对应的SQL语句是:
-- ANSI SQL SELECT * from SalesOrder as tSO LEFT OUTER JOIN SalesOrderLine as tSOL ON (tSO.SalesOrderID = tSOL.SalesOrderID ) where tSOL.Quantity = 66 ;
注意对数量的过滤条件放在了WHERE后,得到的结果集必须满足条件Quantity=66,所以包含子表字段默认值的纪录就被过滤掉了,这就是QueryFitler的作用。
更多内容参见MSDN:http://msdn.microsoft.com/en-us/library/gg881181.aspx