[AX]AX2012开发新特性outer join中使用QueryFilter

假设我们有两张表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

原文地址:https://www.cnblogs.com/duanshuiliu/p/2639677.html