Заполнение пропущенных дней для строк - PullRequest
3 голосов
/ 24 марта 2011

Имеется таблица со схемой, подобной этой:

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 (при условии, что класс существует для стол).

РЕДАКТИРОВАТЬ: столбец дня на самом деле представляет собой int, который представляет день, но ради аргумента, это может быть дата.

Я сделал наивный подход, повторяя каждую группу и добавляя в пропущенные дни, но это кажется ужасно неэффективным. Я должен думать, что что-то происходит быстрее или что кто-то сталкивался с такой ситуацией раньше.

Ответы [ 2 ]

4 голосов
/ 24 марта 2011
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 голос
/ 24 марта 2011

Я начал идти по тому же пути, что и Quassnoi, только в LINQ, но у меня продолжали возникать проблемы. Мне нужно было создать решение, иначе оно меня бы мучило весь день (и мне действительно нужно было поработать). Это решение не так гладко, как ответ Квасного (он получает мой голос), но я потратил время на его выяснение, поэтому подумал, что поделюсь. Это, вероятно, не лучше, чем ваше существующее решение, но я получал удовольствие, делая его:)

// 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);
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...