1

これは、私が作成したより複雑なHQLクエリの1つです。私はまだこの容量でHQLにかなり慣れていないので、フィードバックを使用できます。

ネイティブSQLで行うことの1つは、日付のコマリソンをテーブルとして単一のクエリから取得するように変更することです。

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

それがすべてうまくいくかどうかはわかりません。ステータスのある最後のものは、having句には多すぎる可能性があります。

ただし、パラメーターがnullの場合に省略できるサブクエリがあるため、パフォーマンスはあまり良くありません。私は、DBMSがそれを最適化するのに十分賢いとは思えません。

于 2012-06-06T05:51:46.573 に答える