Как заполнить список значением по умолчанию для записей, которых нет в базе данных? - PullRequest
0 голосов
/ 26 июня 2018

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

Dim PointTotals = db.MemberRewards _
            .Where(Function(r) sitewideFilterSelectedMemberIds.Contains(r.memberId) And r.supplier.name <> "AudStandard" And r.transactionDate >= startDate And r.transactionDate <= EndDate) _
            .GroupBy(Function(r) New With {r.transactionDate.Value.Month, r.transactionDate.Value.Year}) _
            .Select(Function(gr) New With {.month = gr.Key.Month, .year = gr.Key.Year, .totalPoints = gr.Sum(Function(r) r.points)}) _
            .OrderBy(Function(gr) gr.year).ThenBy(Function(gr) gr.month)

Dim firstPeriodDate As Date
Dim currentDate As Date = DateAdd(DateInterval.Month, -1, startDate)

If PointTotals.Count > 0 Then
    Dim firstPeriod = PointTotals.First
    firstPeriodDate = CDate(firstPeriod.month & "/1/" & firstPeriod.year)
Else
    firstPeriodDate = EndDate
End If

Dim months As New List(Of String)
Dim Points As New List(Of Integer)
Do While currentDate < firstPeriodDate
    months.Add(currentDate.ToString("MMM"))
    Points.Add(0)
    currentDate = DateAdd(DateInterval.Month, 1, currentDate)
Loop

For Each period In PointTotals
    months.Add(CDate(period.month & "/1/" & period.year).ToString("MMM"))
    Points.Add(period.totalPoints)
Next

ViewBag.Months = """" & String.Join(""",""", months.ToArray) & """"
ViewBag.Points = String.Join(",", Points.ToArray)

Ответы [ 3 ]

0 голосов
/ 26 июня 2018

Есть много подходов, которые вы можете предпринять, чтобы решить эту проблему, я предложу один DB.

Поскольку вы подключаетесь к базе данных для извлечения ваших данных, вы также можете выполнять суммирование / группирование на стороне БД.

Вы можете сделать это в 3 шага: 1) получить четкий список всех ваших месяцев и сохранить их во временной таблице 2) создайте свои суммы по месяцам и сохраните их в другой временной таблице 3) оставьте присоединение к шагу 1 на шаге 2 (используя месяц в качестве критерия соединения), выполните заказ в любом порядке, который вас интересует, и теперь у вас есть все ваши месяцы.

Существует множество способов реализовать это на стороне SQL, и, как мне показалось, было бы легко следовать приведенному выше подходу.

0 голосов
/ 26 июня 2018

Я думаю, что это более элегантное решение, чем пытаться очистить список после цикла. Единственные изменения в вашем коде - непосредственно перед циклом For Each Period.

Dim PointTotals = db.MemberRewards _
        .Where(Function(r) sitewideFilterSelectedMemberIds.Contains(r.memberId) And r.supplier.name <> "AudStandard" And r.transactionDate >= startDate And r.transactionDate <= EndDate) _
        .GroupBy(Function(r) New With {r.transactionDate.Value.Month, r.transactionDate.Value.Year}) _
        .Select(Function(gr) New With {.month = gr.Key.Month, .year = gr.Key.Year, .totalPoints = gr.Sum(Function(r) r.points)}) _
        .OrderBy(Function(gr) gr.year).ThenBy(Function(gr) gr.month)

        Dim firstPeriodDate As Date
        Dim currentDate As Date = DateAdd(DateInterval.Month, -1, startDate)

        If PointTotals.Count > 0 Then
            Dim firstPeriod = PointTotals.First
            firstPeriodDate = CDate(firstPeriod.month & "/1/" & firstPeriod.year)
        Else
            firstPeriodDate = EndDate
        End If

        Dim months As New List(Of String)
        Dim Points As New List(Of Integer)
        Do While currentDate < firstPeriodDate
            months.Add(currentDate.ToString("MMM"))
            Points.Add(0)
            currentDate = DateAdd(DateInterval.Month, 1, currentDate)
        Loop

        Dim thisPeriodDate As Date
        Dim previousPeriodDate As Date = currentDate
        For Each period In PointTotals
            thisPeriodDate = CDate(period.month & "/1/" & period.year)
            Do While DateDiff(DateInterval.Month, previousPeriodDate, thisPeriodDate) > 1
                months.Add(previousPeriodDate.ToString("MMM"))
                Points.Add(0)
                previousPeriodDate = DateAdd(DateInterval.Month, 1, previousPeriodDate)
            Loop
            months.Add(thisPeriodDate)
            Points.Add(period.totalPoints)
            previousPeriodDate = DateAdd(DateInterval.Month, 1, previousPeriodDate)
        Next

        ViewBag.Months = """" & String.Join(""",""", months.ToArray) & """"
        ViewBag.Points = String.Join(",", Points.ToArray)
0 голосов
/ 26 июня 2018

Похоже, что в вашем коде для добавления пропущенных месяцев вы использовали метод .Add. Вам нужно будет использовать months.Insert (position, CDate (....)) и Points.Insert (position, 0), где position - правильный индекс, чтобы вставить месяц в правильном порядке.

Я мог бы дать вам точные команды, но вы не включили код очистки, на который ссылались в вопросе.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...