2012-01-03 14 views
2

開始日と終了日の間に発生するスケジュールのリストを取得しようとしています。私はすべてのスケジュールの親レコードと子レコードのリストを持っています。このクエリを高速化する方法はありますか?

Schedule 
    Id 

ScheduleDates 
    ScheduleId 
    Start 
    End 

最後の目標は、グループ化された日付のリストを表示できるようにすることです。同じ日に開始して同じ日に終了するスケジュールが複数ある場合は、それらを一緒にグループ化する必要があります。これは私がしたいレコードを返す

var schedules = from schedule in _db.Schedules 
       join date in _db.ScheduleDates on schedule.Id equals date.ScheduleId 
       // join a bunch of other tables 
       // bunch of where queries 
       && date.Start >= startDate 
       && date.Start <= endDate 
       select schedule; 

私は最初と最後の子レコードで一緒のグループにレコードを必要とするとき、私の問題は次のとおりです。

Jan 10 - 15 
    - Schedule 1 
    - Schedule 2 
Jan 10 - 20 
    - Schedule 3 
    - Schedule 4 
Feb 1 - 3 
    - Schedule 5 

最初のクエリは次のようになります。残りは関係ありません。それはちょうどうまく動作しない、次の作品

group new { 
    // 
} by new { 
    Start = schedule.ScheduleDates.Min(x=>x.Start), 
    End = schedule.ScheduleDates.Max(x=>x.Start) 
} 

を追加しようとし

。私は数千が、それは基本的にすべての単一の行のために、次のwhere句でクエリを実行しているため、それは非常に遅い記録していた場合:

WHERE (((@x1 IS NULL) AND (((
    SELECT MIN([t4].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t4] 
    WHERE [t4].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NULL)) OR ((@x1 IS NOT NULL) AND (((
    SELECT MIN([t5].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t5] 
    WHERE [t5].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NOT NULL) AND (((@x1 IS NULL) AND (((
    SELECT MIN([t6].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t6] 
    WHERE [t6].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NULL)) OR ((@x1 IS NOT NULL) AND (((
    SELECT MIN([t7].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t7] 
    WHERE [t7].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NOT NULL) AND (@x1 = ((
    SELECT MIN([t8].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t8] 
    WHERE [t8].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    ))))))) AND (((@x2 IS NULL) AND (((
    SELECT MAX([t9].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t9] 
    WHERE [t9].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NULL)) OR ((@x2 IS NOT NULL) AND (((
    SELECT MAX([t10].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t10] 
    WHERE [t10].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NOT NULL) AND (((@x2 IS NULL) AND (((
    SELECT MAX([t11].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t11] 
    WHERE [t11].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NULL)) OR ((@x2 IS NOT NULL) AND (((
    SELECT MAX([t12].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t12] 
    WHERE [t12].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    )) IS NOT NULL) AND (@x2 = ((
    SELECT MAX([t13].[StartDate]) 
    FROM [dbo].[ScheduleDate] AS [t13] 
    WHERE [t13].[ScheduleDate_ScheduleId] = [t1].[ScheduleId] 
    ))))))) 

私はこれについて何かできることはありますか?

答えて

3

ロジックをC#コードに移動する方が簡単かもしれません.SQLにする必要はありません。

まず、データベースに必要な最小限のデータセットを問い合わせます。次に、データを操作して要件に応じてグループ化するC#を記述します。

SQLは汎用プログラミング言語ではありません!私は労働組合を避ける傾向にあるものの

SELECT * FROM 
(
    SELECT  
    Schedules.Id ScheduleId, 
    MIN(ScheduleDates.Date) Date 
    FROM 
    Schedules INNER JOIN ScheduleDates ON Schedules.Id = ScheduleDates.ScheduleId 
    WHERE 
    ScheduleDates.Date > :1 
    AND ScheduleDate.Date < :2 

    UNION 

    SELECT  
    Schedules.Id ScheduleId, 
    MAX(ScheduleDates.Date) Date 
    FROM 
    Schedules INNER JOIN ScheduleDates ON Schedules.Id = ScheduleDates.ScheduleId 
    WHERE 
    ScheduleDates.Date > :1 
    AND ScheduleDate.Date < :2 
) A 
    ORDER BY ScheduleId, Date 

を、ちょうど一緒にMINとMAXを選択します:これは、SQLステートメントをした場合

2

LINQは、この場合、SQLの上に抽象化されています。すべての抽象化と同様に、それは漏れます。パフォーマンスを向上させるためには、ネイティブSQLにドロップしてそのようなクエリを実行することをお勧めします。 Linq2SQLまたはNhibernateまたはEFを使用しているかどうかは言及していませんが、それぞれに未処理のSQLに到達する方法があります。

0

、私はこれを行うだろう

SELECT 
    Schedules.Id ScheduleId, 
    MIN(ScheduleDates.Date) MinDate, 
    MAX(ScheduleDates.Date) MaxDate, 
FROM 
    Schedules INNER JOIN ScheduleDates ON Schedules.Id = ScheduleDates.ScheduleId 
WHERE 
    ScheduleDates.Date > :1 
    AND ScheduleDate.Date < :2 
GROUP BY Schedules.Id 
ORDER BY Schedules.Id, ScheduleDates.Date 

私はLINQではなく、このSQLを念頭に置いて、誰かがバトンを手に入れて、これを表す正しいLINQを見つけることができると確信しています。とにかく願っています。)

+1

LINQの問題の1つは、作成されたSQLを制御できないことです。あなたは、機能するSQLを生成するプロバイダーの慈悲に敏感ですが、最も最適ではありません。 LINQに何かsimlarを生成させることは可能かもしれませんが、私はそれを本当に疑っています。 –

+0

OK、別の「中間」は、これらのビューの1つを使用してビューを作成し、そのビューでLINQを使用することです。 (必要に応じてフィルタリングするため)と情報マークありがとう=) – Dracorat

関連する問題