2012-03-12 21 views
-1

現在の日のすべてのイベントと、recurring = 1のすべてのイベントを返すSQL(Server)クエリを作成しようとしていますが、その日にこのイベントを返すようにしたいそのイベントの後の52週間にわたって開催されています。複雑なSQL Serverクエリ

私のテーブルは以下のように構成されています

Event 
{ 
    event_id (PK) 
    title, 
    description, 
    event_start DATETIME, 
    event_end DATETIME, 
    group_id, 
    recurring 
} 

Users 
{ 
    UserID (PK) 
    Username 
} 

Groups 
{ 
    GroupID (PK) 
    GroupName 
} 

Membership 
{ 
    UserID (FK) 
    GroupID (FK) 
} 

私はこれまで、次のされているように、コード:これは、イベントの日付のための1つのクエリが中に保存した場合、その結果

 var db = Database.Open("mPlan"); 
    string username = HttpContext.Current.Request.Cookies.Get("mpUsername").Value; 
    var listOfGroups = db.Query("SELECT GroupID FROM Membership WHERE UserID = (SELECT UserID from Users WHERE Username = @0)", username); 
    foreach(var groupID in listOfGroups) 
     { 
      int newGroupID = groupID.GroupID; 
      var result = db.Query(
       @"SELECT e.event_id, e.title, e.description, e.event_start, e.event_end, e.group_id, e.recurring 
       FROM event e 
       JOIN Membership m ON m.GroupID = e.group_id 
       WHERE e.recurring = 0 
       AND m.GroupID = @0 
       AND e.event_start >= @1 
       AND e.event_end <= @2 
       UNION ALL 
       SELECT e.event_id, e.title, e.description, DATEADD(week, w.weeks, e.event_start), DATEADD(week, w.weeks, e.event_end), e.group_id, e.recurring 
       FROM event e 
      JOIN Membership m ON m.GroupID = e.group_id 
      CROSS JOIN 
       (SELECT row_number() OVER (ORDER BY Object_ID) AS weeks 
       FROM SYS.OBJECTS 
       ) AS w 
       WHERE e.recurring = 1 
       AND m.GroupID = @3 
       AND DATEADD(WEEK, w.Weeks, e.event_start) >= @4 
       AND DATEADD(WEEK, w.Weeks, e.event_end) <= @5", newGroupID, start, end, newGroupID, start, end 
      ); 

このイベントと52週間のイベントが返されます。このイベントの1週間後にイベントを照会すると、何も返されません。

+0

可能な複製[オブジェクト型WebMatrix.Data.DynamicRecordから既知の管理プロバイダのネイティブ型へのマッピングが存在しません](http://stackoverflow.com/questions/9665051/no-mapping-exists-from-object-type) -webmatrix-data-dynamic-record-known-manag) –

+0

あなたの他の質問の答えは、あなたのエラーの方向にあなたを指摘しました...それはあなたのSQLとは関係ありません - 代わりに、 'DynamicRecord'である' groupID'を 'db.Query'に追加します。前の結果セットから値を取得し、それをintに変換する必要があります。または、あなたがメインクエリで追加の結合を行う代わりに 'foreach'を使う理由がないので、このコードを書き直すことをお勧めします。 –

+0

@MichaelFredrickson、応答ありがとう。私はこれをやろうとしていますが、SQL ServerとC#の初心者として苦労しています。あなたは、あなたが提案した参加を使って書くことができる別のクエリを提案してもらえますか?そのようなコードを書くのに必要なスキルはほとんどないでしょうか? –

答えて

1

最も簡単な解決策は

AND DATEADD(WEEK, w.Weeks, e.event_start) >= @4 
AND DATEADD(WEEK, w.Weeks, e.event_end) <= @5" 

に次の2行

AND e.event_start >= @4 
AND e.event_end <= @5" 

を変更するだろうしかし、私は保存にすべてこのSQLを入れてお勧めしますプロシージャを実行すると、SQL Serverは実行計画をキャッシュし、パフォーマンスが(わずかに)向上します。

CREATE PROCEDURE dbo.GetEvents @UserName VARCHAR(50), @StartDate DATETIME, @EndDate DATETIME 
AS 
BEGIN 
-- DEFINE A CTE TO GET ALL GROUPS ASSOCIATED WITH THE CURRENT USER 
;WITH Groups AS 
( SELECT GroupID 
    FROM Membership m 
      INNER JOIN Users u 
       ON m.UserID = u.UserID 
    WHERE Username = @UserName 
    GROUP BY GroupID 
), 
-- DEFINE A CTE TO GET ALL EVENTS FOR THE GROUPS DEFINED ABOVE 
AllEvents AS 
( SELECT e.* 
    FROM event e 
      INNER JOIN Groups m 
       ON m.GroupID = e.group_id 
    UNION ALL 
    SELECT e.event_id, e.title, e.description, DATEADD(WEEK, w.weeks, e.event_start), DATEADD(WEEK, w.weeks, e.event_end), e.group_id, e.recurring 
    FROM event e 
      INNER JOIN Groups m 
       ON m.GroupID = e.group_id 
      CROSS JOIN 
      ( SELECT ROW_NUMBER() OVER (ORDER BY Object_ID) AS weeks 
       FROM SYS.OBJECTS 
      ) AS w 
    WHERE e.recurring = 1 
) 
-- GET ALL EVENTS WHERE THE EVENTS FALL IN THE PERIOD DEFINED 
SELECT * 
FROM AllEvents 
WHERE Event_Start >= @StartDate 
AND  Event_End <= @EndDate 

END 

その後、あなたはこれが背後にあるコード内でグループを反復処理する必要性をelimates

var result = db.Query("EXEC dbo.GetEvents @0, @1, @2", username, start, end); 

でこれを呼び出すことができます。これが実際に必要な場合は、ストアドプロシージャを変更して@GroupIDをパラメータとして使用し、select文/ where句を必要に応じて変更できます。

私はCommon Table Expressionsの知識を前提としています。彼らはクエリを動作させる必要はありません、彼らはちょっと私の意見では少し読みやすくします。私は必要があればそれらなしでこれを書き換えることができます。

+0

この回答には本当に感謝しています。初心者としては本当に役に立ちます。ありがとうございました。私は自分のコードを編集して、最初に動作するようにしようとしています(最初に提供したより簡単なソリューション)。私はまだ問題を抱えていますが、現在は何のイベントも戻っていません。上記のコードを編集して、現在実行中のものを表示します。私はあなたが示唆した他の変更を行うことを設定する前に、任意のアイデア? :) –

+1

@GarethdDまた、それはINNER JOINグループm にする必要がありますm.GroupID = egroup_id?おもう?私は完全に推測しているので、コンパイルするにはどうすればいいのでしょうか? –

+0

今、私はそれをコンパイルして、ちょっとしたエラーで - イベントはすべての日付で返されます。 –

1

私はいくつかの簡単なSQLに対して一度に1つずつパラメータをチェックして、可能な限り犯人を排除します。このような何か:

var result = db.Query("select r=cast(@0 as varchar(80))",username); 
var result = db.Query("select r=cast(@0 as int)",newGroupID); 
var result = db.Query("select r=cast(@0 as datetime)",start); 
var result = db.Query("select r=cast(@0 as datetime)",end); 
+0

これはエラーですが、私はそれを修正し、残念ながら私のコードはまだ動作しません! –

+0

SQLをデバッグして印刷し、SSMSで実行できますか? –

+0

@は2番目のクエリの前にありますか?最初のものの前にはないことがわかりました。@ @ "SELECT" –