1

这是我编写的更复杂的 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>();            
        }
4

1 回答 1

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)))

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

但是,它的性能不是很好,因为当参数为空时,可以省略一些子查询。我怀疑 DBMS 是否足够聪明以优化它。

于 2012-06-06T05:51:46.573 回答