C# 复杂的SQL Server查询
我正在尝试编写一个SQL Server查询,该查询将返回当前日期的所有事件,对于列recurtive=1的所有事件,我希望它在事件发生当天以及事件发生后的52周内返回此事件 我的表格结构如下: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
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);