Как сгруппировать по дате и времени в c# для указанного диапазона c? - PullRequest
0 голосов
/ 03 августа 2020

В моем приложении as pnet core 3.1 я использую шаблон CQRS. У меня есть сводная таблица, которая рассчитывается каждый час (фоновая работа Hangifre) некоторая цена

Пример данных выглядит так:

Price - 10, StartDate - 2020/08/02 10:00 , EndDate - 2020/08/03 11:00
Price - 10, StartDate - 2020/08/02 11:00 , EndDate - 2020/08/03 12:00
Price - 10, StartDate - 2020/08/02 13:00 , EndDate - 2020/08/03 14:00
Price - 10, StartDate - 2020/08/02 14:00 , EndDate - 2020/08/03 15:00
Price - 10, StartDate - 2020/08/02 15:00 , EndDate - 2020/08/03 16:00
Price - 10, StartDate - 2020/08/02 16:00 , EndDate - 2020/08/03 17:00

Я хотел бы получить что-то вроде: если я укажу periodDuration = 3ч

Price - 30, StartDate - 2020/08/02 10:00 , EndDate - 2020/08/03 13:00
Price - 30, StartDate - 2020/08/02 13:00 , EndDate - 2020/08/03 16:00
Price - 30, StartDate - 2020/08/02 19:00 , EndDate - 2020/08/03 22:00

Мой метод выглядит так:

        var billing = _context.BillingSummaries.AsQueryable();         

        switch (request.SortBy)
        {
            case "createdAt" when request.SortDirection == "asc":
                billing = billing.OrderBy(x => x.BeginApply);
                break;
            case "createdAt" when request.SortDirection == "desc":
                billing = billing.OrderByDescending(x => x.BeginApply);
                break;
        }

        if (request.StartDate.HasValue)
        {
            billing = billing.Where(x =>
                x.BeginApply >= request.StartDate);
        }

        if (request.EndDate.HasValue)
        {
            billing = billing.Where(x =>
                x.EndApply <= request.EndDate);
        }

        // Want to achieve this
        billing = request.PeriodDuration switch
        {
            "3h" => "calculate 3 hours range",
            "6h" => "calculate 6 hours range",
            "12h" => "calculate 12 hours range",
            "d" => "calculate daily range",
            "w" => "calculate weekly range",
            "m" => "calculate monthly range",
            _ => billing
        };

        var billings = await billing.Skip(request.Offset ?? 0).Take(request.Limit ?? 50)
            .ToListAsync(cancellationToken: cancellationToken);

        if (billings == null)
            throw new NotFoundException("Not found");

        return new BillingInfo
        {
            Data = _mapper.Map<List<BillingSummary>, List<BillingSummaryDto>>(billings),
            TotalCount = await billing.CountAsync(cancellationToken: cancellationToken),
            AllPrice = await billing.SumAsync(x => x.Price, cancellationToken: 
             cancellationToken),
            Currency = currency.ToString("G")
        };

Ответы [ 2 ]

0 голосов
/ 13 августа 2020

сначала сгруппируйте данные по дате, а затем попробуйте

 public class Billingdata
{
    public int Price { get; set; }
    public DateTime Start { get; set; }
    public DateTime End { get; set; }
}
public class GroupingData {
    public int Start { get; set; }
    public int End { get; set; } 
}
var timerangelist = new List<GroupingData> { 
        new GroupingData{ Start = 10, End=13 },
        new GroupingData{ Start = 13, End=16 },
        new GroupingData{ Start = 16, End=19 },
        new GroupingData{ Start = 19, End=22 },

        };
        var result = new List<Billingdata>();

        var billings = new List<Billingdata> {
        new Billingdata{Price = 10, Start = new DateTime(2020,08,02,10,00,00), End = new DateTime(2020,08,02,11,00,00) },
        new Billingdata{Price = 10, Start = new DateTime(2020,08,02,11,00,00), End = new DateTime(2020,08,02,12,00,00) },
        new Billingdata{Price = 10, Start = new DateTime(2020,08,02,12,00,00), End = new DateTime(2020,08,02,13,00,00) },
        new Billingdata{Price = 10, Start = new DateTime(2020,08,02,13,00,00), End = new DateTime(2020,08,02,14,00,00) },
        new Billingdata{Price = 10, Start = new DateTime(2020,08,02,14,00,00), End = new DateTime(2020,08,02,15,00,00) },
        new Billingdata{Price = 10, Start = new DateTime(2020,08,02,15,00,00), End = new DateTime(2020,08,02,16,00,00) },
        new Billingdata{Price = 10, Start = new DateTime(2020,08,02,16,00,00), End = new DateTime(2020,08,02,17,00,00) }
        };
        foreach (var item in timerangelist)
        {
            var data = billings.Where(w => item.End >= w.End.Hour && w.Start.Hour >= item.Start).ToList();
            var p = data.Sum(s => s.Price);
            var ss = data.FirstOrDefault(f => f.Start.Hour == item.Start)?.Start;
            var e = data.FirstOrDefault(f => f.End.Hour == item.End)?.End;
            if (ss == null || e == null) { continue; }
            result.Add(
                new Billingdata { Price = p, 
                    Start = (DateTime)ss,
                    End = (DateTime)e,
                }
                );
        }



enter code here
0 голосов
/ 03 августа 2020

Предположим, что сырые данные всегда охватывают один час каждый.

billing = request.PeriodDuration switch
{
    "3h" => (
        from b in billing
        group b by new Hourly { b.StartDate.Year, b.StartDate.Month, b.StartDate.Day, Hour = b.StartDate.Hour / 3 } into groups
        from bs in groups
        select new
        {
            Price = bs.Sum(b => b.Price),
            StartDate = bs.Min(p => p.StartDate),
            EndDate = bs.Max(p => p.EndDate)
        }
    ),
    "6h" => (
        from b in billing
        group b by new Hourly { b.StartDate.Year, b.StartDate.Month, b.StartDate.Day, Hour = b.StartDate.Hour / 6 } into groups
        from bs in groups
        select new
        {
            Price = bs.Sum(b => b.Price),
            StartDate = bs.Min(p => p.StartDate),
            EndDate = bs.Max(p => p.EndDate)
        }
    ),
    "12h" => (
        from b in billing
        group b by new Hourly { b.StartDate.Year, b.StartDate.Month, b.StartDate.Day, Hour = b.StartDate.Hour / 12 } into groups
        from bs in groups
        select new
        {
            Price = bs.Sum(b => b.Price),
            StartDate = bs.Min(p => p.StartDate),
            EndDate = bs.Max(p => p.EndDate)
        }
    ),
    "d" => (
        from b in billing
        group b by new Daily { b.StartDate.Year, b.StartDate.Month, b.StartDate.Day } into groups
        from bs in groups
        select new
        {
            Price = bs.Sum(b => b.Price),
            StartDate = bs.Min(p => p.StartDate),
            EndDate = bs.Max(p => p.EndDate)
        }
    ),
    "w" => (
        from b in billing
        group b by new { b.StartDate.Year, Week = SqlFunctions.DatePart("week", b.StartDate) } into groups
        from bs in groups
        select new
        {
            Price = bs.Sum(b => b.Price),
            StartDate = bs.Min(p => p.StartDate),
            EndDate = bs.Max(p => p.EndDate)
        }
    ),
    "m" => (
        from b in billing
        group b by new { b.StartDate.Year, b.StartDate.Month } into groups
        from bs in groups
        select new
        {
            Price = bs.Sum(b => b.Price),
            StartDate = bs.Min(p => p.StartDate),
            EndDate = bs.Max(p => p.EndDate)
        }
    ),
    _ => billing
};
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...