2011-02-07 13 views
8

私は、かなり単純なデータベースでレポートを作成するために次元モデリングなどのデータウェアハウジングの原則を使用するアプリケーションを持っています。コールという名前SQLの統計クエリ - これはNHibernate LINQで可能ですか?

例(簡体字)エンティティは次のようになります。

public virtual long Id { get; set; } 
    public virtual string OriginatorNumber { get; set; } 
    public virtual string DestinationNumber { get; set; } 
    public virtual DateDimension DateDimension { get; set; } 

彼らは無関係であるとして、実際のモデルのプロパティのいくつかは削除されました。簡略化されDateDimensionは次のようになります。

public virtual long Id { get; set; } 
    public virtual DateTime Date { get; set; } 
    public virtual int DayOfMonth { get; set; } 
    public virtual int Weekday { get; set; } 

このような多くの列があります - 彼らは、アプリケーションのセットアップによって、現在の十年のために事前に設定されています。したがって、この10年間の各日付にはこの表の行があり、各呼び出しには発生した日付へのリンクがあります。これはすべてFluent NHibernateにマップされており、うまく動作します。

私はいくつかの報告をしたい場合、3.0で改善されたNHibernate LINQプロバイダでこれを簡単に行うことができます。メンテナンス性を向上させるためにLINQを使用したいと思いますが、もし本当に必要ならば、HQL、ICriteria、あるいは普通のSQLを考慮します。

だから、特定の番号からのコール数を発生した曜日で割った数を示すレポートを作成したいとします。私は簡単にこのようにそれを行うことができます。この例では

 var query = Calls 
      .Where(c => c.OriginatorNumber == "402") 
      .GroupBy(c => c.DateDimension.Weekday) 
      .Select(g => new { Day = g.Key, Calls = g.Count() }); 

を、「コール」のIQueryableリポジトリインタフェースを介してNHibernates LINQプロバイダ(クエリ)から返された基本的です。上のクエリは私に正しい結果を与え、NHibernate ProfilerはSQLがかなり最適であり、すべてがうまくいることを示しています。

しかし、少し前進させたいと思ったら、私は立ち往生します。私は平日の平均コール数を求めています。上記から遠すぎず、そうですか?結果セットにある毎日のユニークな日付の数を把握し、コールの総数をそれで割る必要があります。私たちはすべて正しく設定されていますか?さて、いいえ、ここで私はNHibernate LINQプロバイダの限界に着手します。オブジェクトへのLINQで、私はそれを行うには、クエリを構築することができ -

.Select(g => g.Count()/g.GroupBy(c => c.DateDimension.Date).Count()); 

の線に沿って何かをNHibernateの中でそれを使用している場合しかし、これが正しいクエリに変換されません。むしろ、上記の両方の.Count()呼び出しを呼び出しレコードの同じカウント(*)に変換するので、結果は常に1になります。

もちろん、各呼び出し、曜日、日付をa新しい匿名オブジェクトは、アプリケーション側で数学を行いますが、従来の知恵によれば、それはちょうど間違っています(tm)。私は絶望でそれをやり遂げることができた、tho、それは百万コールにテーブルが成長するときそれは痛みを意味する。

以下は、私が探している結果を与えるSQLクエリです。

select ss.Weekday, AVG(cast(ss.Count as decimal)) 
from 
(
select dd.Weekday, dd.Date, COUNT(*) as Count 
from Call c 
left outer join DateDimension dd 
    on c.DateDimension_id = dd.Id 
where c.OriginatorNumber = '402' 
group by dd.Weekday, dd.Date 
) ss 
group by ss.Weekday 
order by ss.Weekday 

それはNHibernateはLINQプロバイダでこれを行うことは可能ですか?それが不可能な場合は、アプリケーションに中間結果を取得させて残りの作業をさせる前に、どれくらい近づけることができますか?

+0

多分あなたはそれについて間違った方法を行っているでしょう。スタースキーマを作成し、計算された数値データを事前に入力する方法はありますか? – epitka

+0

それは興味深い点ですが、私の理解では、「事実」テーブル(つまり、私の例ではコール)の各エンティティは、それぞれの関連するディメンションテーブルに対して1つのFKを持っています。スタースキーマを作成すると、コールの日付を把握するのに役立ち、各コールのレコードからそのコールをポイントすることができます。しかし、一般的に、私はこれを間違った方法で行おうとしている可能性が非常に高いです。 :) –

答えて

1

LINQプロバイダではできないことがたくさんあります。 HQLまたはCreateCriteriaを使うことは、NHibernateで受け入れなければならないものです。

私はそれを試していませんが、HQLまたはCreateCriteria(DetatchedCriteriaを使用)を使用してやりたいことができるはずです。

あなたは、CreateSqlQueryを使用してプレーンSQLにフォールバックすることもできます。

+1

こんにちは、あなたの返事に感謝します。はい、私はこれに落ちるかもしれません - 問題は基本的に私はIQueryable に基づいてAPIをユーザに提示したいので、グループ化のためにIQueryableを渡す前にWhere()でフィルタリングを行うことができます。私は本当にすべきことは、素晴らしいコーダーになり、NHibernateに貢献することだと思います。 :)入力をありがとう、私は物事を行うHQLとICriteriaの方法を見ていきます。 –

関連する問題