C# 复杂的SQL Server查询

C# 复杂的SQL Server查询,c#,sql,sql-server,database,C#,Sql,Sql Server,Database,我正在尝试编写一个SQL Server查询,该查询将返回当前日期的所有事件,对于列recurtive=1的所有事件,我希望它在事件发生当天以及事件发生后的52周内返回此事件 我的表格结构如下: Event { event_id (PK) title, description, event_start DATETIME, event_end DATETIME, group_id, recurring } Users { UserID

我正在尝试编写一个SQL Server查询,该查询将返回当前日期的所有事件,对于列recurtive=1的所有事件,我希望它在事件发生当天以及事件发生后的52周内返回此事件

我的表格结构如下:

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周的事件。当一个人在这一周后查询事件时,什么也不会返回。

我会根据一些琐碎的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);

最简单的解决方案是更改以下两行

AND    e.event_start >= @4
AND    e.event_end <= @5"
这就省去了在代码隐藏中迭代组的需要。如果这实际上是一个需求,那么您可以修改存储过程以@GroupID作为参数,并根据需要更改select语句/where子句


我假定我知道。他们不需要让查询工作,他们只是让事情在我看来更加清晰。如果需要的话,我可以在没有它们的情况下重写它。

这是一个错误,但是我已经更正了它,很遗憾,我的代码仍然无法工作!是否可以打印SQL并在SSMS中运行?@是否属于第二个查询的前面?我注意到它不在第一个前面@选择Yes,确实如此,我相信这只是一个多行查询!非常感谢您的回复。我已经按照你的建议编辑了我的代码,现在我有一个新的错误。当查询数据库中存储的事件日期时,将返回此事件和52周的事件。当一个人在本周之后查询事件时,不会返回任何内容。有什么方法可以根据生成的日期时间检查参数“开始”和“结束”吗?其他问题中答案的可能重复为您指出了错误的方向。。。它与您的SQL无关—相反,您正在尝试将groupID(一个DynamicRecord)传递到db.Query。您需要从上一个结果集中获取值,并将其转换为int。或者,我建议重新编写此代码,因为我看不出您为什么要使用foreach而不是在主查询中进行额外的连接…@MichaelFredrickson,感谢您的回复。我正在尝试这样做,但正如你所知,我作为一名SQL Server和C的初学者正在努力。你介意推荐一个我可以使用你建议的连接编写的替代查询吗,因为我几乎没有编写这样一段代码所需的技能吗?@MichaelFredrickson,我真的不确定在这种情况下联接是如何工作的,因为在Groups表中,可以有多个相同UserID的实例@MichaelFredrickson我已经编辑了上面的代码,这样C中的groupID就没有错误了。查询返回OK,但是没有结果,即使我已经将它们添加到了我的表中。非常感谢您的回答-这对我这个初学者来说真的很有帮助。非常感谢。我试图简单地编辑我的代码,以便它能够在您提供的第一个更简单的解决方案中首先工作。我仍然有一个问题,虽然,它目前没有返回任何事件。我已经编辑了上面的代码,以显示我当前正在运行的内容。在我开始做你建议的其他改变之前,有什么想法吗@GarethdD还应该是m.GroupID=e.GroupID\u id上的内部连接组m吗?我想?我完全在猜测,因为这就是我编译它的方式:现在我正在编译它,只出现一个小错误——事件将针对每个日期返回…除了添加的日期@SimonKiely是的,对不起,应该是m.GroupID而不是e.GroupID。我已经更新了我的答案,我还纠正了第一个重复事件没有返回的问题。太棒了。我已经在这段代码上工作了好几个星期,而你只用了几个小时就完成了。难以置信的非常非常感谢。
AND    DATEADD(WEEK, w.Weeks, e.event_start) >= @4
AND    DATEADD(WEEK, w.Weeks, e.event_end) <= @5"
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);