0

我正在使用 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 日的日期是星期一,并且 Monday 设置为 true,那么当天会有一段旅程。

我正在尝试将它们插入到它们运行的​​每一天的新表行中,这样就变成了:

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# 中也有一个版本,但速度稍慢 - 尽管它确实使用了类似的过程(它使用嵌套循环过程,然后保存要插入到通用列表中的项目,然后批量插入它们)

当前使用的过程循环遍历每个旅程,并且在每个旅程中,循环遍历开始日期和结束日期之间的每个日期,以检查它落在哪一天以及该日期是否设置为 true。这可能需要很长时间才能执行。

谁能想到一种更有效的方法来执行此插入?它目前每小时可以循环约 100,000 次行程,但可能有数百万次行程,因此可能需要很长时间。

4

2 回答 2

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
于 2012-10-19T09:39:24.250 回答
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

通过适当的索引,这应该会产生良好的性能。

于 2012-10-19T11:56:53.820 回答