填写行的缺失日期

时间:2011-03-24 15:24:52

标签: sql-server linq-to-sql

给定一个包含这样的模式的表:

id1    id2    day    number

我该怎么做呢:

a    b    day1    2
a    b    day5    4
a    b    day9    8
c    d    day2    1
c    d    day3    2
c    d    day5    4
c    d    day8    3

进入这个?:

a    b    day1    2
a    b    day2    2
a    b    day3    2
a    b    day4    2
a    b    day5    4
a    b    day6    4
a    b    day7    4
a    b    day8    4
a    b    day9    8
c    d    day2    1
c    d    day3    2
c    d    day4    2
c    d    day5    4
c    d    day6    4
c    d    day7    4
c    d    day8    3

为了澄清,对于每组id1和id2,我需要填写缺失的行 日期范围从该分组的最小日期到最大日期 日期。此外,填充的行必须使用前一个条目 它的数字列的数字列。

我需要这个尽快运行。

如果你能在LINQ to SQL中做到这一点,那么

奖励点(假设该类存在于 表)。

编辑:day列实际上是一个表示日期的int,但为了参数,它可能是一个日期。

我已经完成了对每个组进行迭代并添加缺失日期的天真方法,但它看起来非常低效。我不得不认为有更快的事情,或者某人之前遇到过这种情况。

2 个答案:

答案 0 :(得分:4)

WITH    dates (id1, id2, ds, de) AS
        (
        SELECT  id1, id2, MIN(d), MAX(d)
        FROM    mytable m
        GROUP BY
               id1, id2
        UNION ALL
        SELECT  d.id1, d.id2, DATEADD(d, 1, ds), de
        FROM    dates d
        WHERE   ds < de
        )
SELECT  id1, id2, ds, m.number
FROM    dates d
CROSS APPLY
        (
        SELECT  TOP 1 number
        FROM    mytable m
        WHERE   m.id1 = d.id1
                AND m.id2 = d.id2
                AND m.d <= d.ds
        ORDER BY
                m.d DESC
        ) m
OPTION (MAXRECURSION 0)

答案 1 :(得分:1)

我开始沿着与Quassnoi相同的路径只在LINQ,但我一直有问题。我不得不创建一个解决方案,否则它会让我整天烦恼(我真的需要完成一些工作)。这个解决方案并不像Quassnoi的答案那样光滑(他得到了我的投票),但我花了一些时间搞清楚,所以我想我会分享。这可能不比现有的解决方案好,但我很乐意制作它:)

// This selects each id group with their min and max dates into a collection
var query = (from m in MissingDaysTables
group m by new {Id1 = m.Id1, Id2 = m.Id2, } into myGroup
select new 
{ 
    Id1=myGroup.Key.Id1, 
    Id2=myGroup.Key.Id2, 
    StartDay=(from g in myGroup select g.Day).Min(), 
    EndDay=(from g in myGroup select g.Day).Max()
});

var myList = new List<MissingDaysTable>();

// Loop through each group and create the records
foreach (var row in query)
{
    DateTime curDate = row.StartDay; //used to track the current date
    while (curDate <= row.EndDay)
    {
        myList.Add(new MissingDaysTable() 
        { 
            Id1 = row.Id1, 
            Id2 = row.Id2, 
            Day=startDate, 
            Number=MissingDaysTables.Where(m => m.Id1==row.Id1 && m.Id2==row.Id2 && m.Day<=curDate).OrderByDescending (t => t.Day).First().Number
        });
        curDate = curDate.AddDays(1);
    }
}