我正在使用ASP.NET MVC3应用程序,我有一个用于公共汽车旅程的数据库表,其中列出了开始和结束日期以及操作日期。以下是一个片段:
JourneyID StartDate EndDate Monday Tuesday Wednesday etc
676 02 Jan 2012 01 Mar 2012 True False True etc
696 02 Jan 2012 01 Mar 2012 False False True etc
650 02 Jan 2012 25 Mar 2012 True True True etc
因此,如果2012年1月2日的日期是星期一,星期一设置为真,那么那天就有一段旅程。
我正在尝试将这些插入到他们运行的每一天的新表行中,这样就会变成:
JourneyID Date
676 02 Jan 2012
676 04 Jan 2012
696 04 Jan 2012
650 02 Jan 2012
650 03 Jan 2012
当前在系统上执行此操作的查询非常慢 - 它在t-sql中使用嵌套的while循环。在C#中也有一个版本,但稍微慢了 - 尽管它确实使用了类似的过程(它使用了嵌套循环过程,然后保存了要插入通用列表的项目,然后批量插入它们)
正在使用的流程目前遍历每个旅程,并且在每个旅程中,循环开始和结束日期之间的每个日期以检查它落在哪一天以及该日期是否设置为真。这可能需要很长时间才能完成。
有人能想到更有效的方法来执行此插入吗?它目前每小时可以循环约100,000次,但可能会有数百万次旅行,因此可能需要很长时间。
答案 0 :(得分:1)
有效地,你是在解开,然后过滤。
;with cte as
(
select JourneyID, StartDate,EndDate,Days
from yourtable s unpivot (active for days in (Monday, tuesday, wednesday, ...)) u
where active = 1
)
select JourneyID, JourneyDate
from (
select
DATEADD(D, number, (Select MIN(startdate) from cte)) as JourneyDate
from master..spt_values
where type='p'
and number < (select datediff(d,MIN(StartDate),max(enddate)) from cte)
) numbers
cross join cte
where
days = datename(weekday, JourneyDate)
and JourneyDatebetween StartDate and EndDate
order by JourneyDate, JourneyID
答案 1 :(得分:0)
创建日历表并加入。星期几是你的表设置有点棘手(布尔星期一,星期二等)。如果你将游览运行的日期规范化并提取到子表,那将会容易得多。
通过这样的设置,您可以编写如下查询:
INSERT INTO NewTable (Journey, Date)
SELECT J.JourneyId, C.Date FROM Journey J
INNER JOIN JourneyWeekdays JW ON J.Id = JW.JourneyId
INNER JOIN Calendar C ON (C.Date BETWEEN JT.StartDate AND JT.EndDate) AND C.DayOfWeek = JW.DayOfWeek
通过适当的索引,这应该会带来良好的性能。