如何优化此Nhibernate HQL查询?

时间:2012-06-06 05:27:29

标签: nhibernate query-optimization hql

这是我编写的更复杂的HQL查询之一。我仍然对这个容量的HQL很新,可以使用一些反馈。

我在本机sql中要做的一件事就是将日期comarison东西改成单个查询作为表格,即

FROM 
(
    SELECT MIN, MAX
    FROM ..
) T

以下是方法:

public IList<Order> GetOrdersBy(string referenceNumber = null, int? customerId = null, int? carrierId = null, DateTime? startDate = null,
            DateTime? endDate = null, int? websiteId = null, OrderStatus? status = null)
        {


            var byStatusHql =
            @"
            select odor
            from Order odor
            join fetch odor._orderStatusLog statusLog
            where 
            (:referenceNumber is null or odor.Quote.ReferenceNumber=:referenceNumber) and
            (:customerId is null or odor.Quote.Customer.CustomerID=:customerId) and
            (:carrierId is null or odor.Quote.Carrier.CarrierID=:carrierId) and
            (:websiteId is null or odor.Quote.Customer.Website.WebsiteID=:websiteId) and
            (
                :startDate is null or :startDate >
                (select min(CreatedDate) from OrderStatusLog lg where lg in elements(odor._orderStatusLog))
            ) and
            (
                :endDate is null or :endDate <= 
                (select max(CreatedDate) from OrderStatusLog lg where lg in elements(odor._orderStatusLog))
            ) and
            (
                :status is null or :status = 
                (
                    select Status from OrderStatusLog lg where lg in elements(odor._orderStatusLog) 
                    and lg.OrderStatusLogID = (select max(OrderStatusLogID) from OrderStatusLog lgg where lgg in elements(odor._orderStatusLog))
                )

            )
            ";

            var query = Session.CreateQuery(byStatusHql);
            query.SetParameter("referenceNumber", referenceNumber)
                 .SetParameter("customerId", customerId)
                 .SetParameter("carrierId", carrierId)
                 .SetParameter("websiteId", websiteId)
                 .SetParameter("startDate", startDate)
                 .SetParameter("endDate", endDate)
                 .SetParameter("status", status)
            ;

            return query.List<Order>();            
        }

1 个答案:

答案 0 :(得分:0)

您的意思是“优化”在性能或可读性方面吗?

考虑到性能,我会使用Criteria或QueryOver来仅添加实际使用的过滤器参数。标准不是那么强大,在这种情况下语法会更复杂,但动态组合查询更容易。

您可以尝试在日志中使用单个子查询来聚合:

and exists (
    select min(CreatedDate), max(CreatedDate), max(OrderStatusLogID) 
    from OrderStatusLog lg 
    where lg in elements(odor._orderStatusLog)
    having 
      :startDate is null or :startDate > min(CreatedDate)
      and :endDate is null or :endDate <= max(CreatedDate)
      and :status is null or :status = (
        select lgg.Status from OrderStatusLog lgg 
        where lgg.id = max(OrderStatusLogID)))

我不知道这一切是否奏效。带状态的最后一个对于having子句来说可能太多了。

但是,它执行得不是很好,因为当参数为null时,可以省略子查询。我怀疑DBMS是否足够智能以优化它。