2012-03-12 95 views
-1

我想寫一個SQL(服務器)查詢將返回當天的所有事件,併爲所有事件列recurring = 1,我希望它在當天返回此事件正在舉行,並在事件發生後的52周內舉行。作爲跟隨複雜的SQL服務器查詢

我的表結構:

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

我迄今如下代碼:

 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周的事件被返回。當人們在這一週之後的一個星期查詢事件時,什麼都不會返回。

+0

可能存在[存在從對象類型WebMatrix.Data.DynamicRecord到已知託管提供程序本機類型的映射]的副本(http://stackoverflow.com/questions/9665051/no-mapping-exists-from-object-type -webmatrix-data-dynamicrecord-a-known-manag) – 2012-03-12 20:42:16

+0

你的其他問題的答案指出你錯誤的方向......它與你的SQL無關 - 相反,你試圖通過在'groupID',這是一個'DynamicRecord','db.Query'。您需要從先前的結果集中獲取值,並將其轉換爲int。或者,我建議重新編寫這段代碼,因爲我沒有看到爲什麼你會使用'foreach'而不是在你的主查詢中進行額外的連接... – 2012-03-12 20:45:03

+0

@MichaelFredrickson,謝謝你的迴應。我試圖做到這一點,但正如你可以告訴我,作爲初學者與SQL Server和C#掙扎。您是否介意提出我可以使用您建議的連接編寫的替代查詢,因爲我幾乎沒有編寫這樣一段代碼所需的技能? – 2012-03-12 20:53:31

回答

1

最簡單的解決辦法是將以下兩行

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

改成

AND DATEADD(WEEK, w.Weeks, e.event_start) >= @4 
AND DATEADD(WEEK, w.Weeks, 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 

然後你就可以用

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

這elimates需要在你的代碼遍歷組後調用它。如果這實際上是一個需求,那麼您可以修改存儲過程以將@GroupID作爲參數,並根據需要更改select語句/ where子句。我知道Common Table Expressions。他們不需要使查詢工作,他們只是讓我的意見稍微清晰一些。如果需要,我可以在沒有它們的情況下重寫。

+0

非常感謝你的答案 - 這對我作爲初學者非常有幫助。謝謝。我試圖編輯我的代碼,以便它能夠首先工作(您提供的第一個,更簡單的解決方案)。我仍然有一個問題,但它目前沒有返回任何事件。我已經編輯了上面的代碼來顯示我目前正在運行的代碼。任何想法,在我着手進行你提出的其他改變之前? :) – 2012-03-12 23:02:12

+1

@GarethdD另外,應該是INNER JOIN組m ON m.GroupID = instancesroup_id?我認爲?我完全猜測,因爲那是我怎麼編譯:) – 2012-03-12 23:17:39

+0

現在我有它編譯,有一個小錯誤 - 事件正在返回每個日期...除了它添加的日期! – 2012-03-12 23:22:19

1

我會檢查我的參數一次一個反對一些微不足道的SQL,只是爲了排除可能的罪魁禍首。事情是這樣的:

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

這是一個錯誤,但我已糾正它,並且我的代碼仍然不能工作! – 2012-03-12 20:31:46

+0

是否可以調試打印SQL並在SSMS中運行? – 2012-03-12 20:34:42

+0

@屬於第二個查詢?我注意到它不在第一個前面。「@」SELECT' – 2012-03-12 20:40:46