【问题标题】:How select rows with grouping by month如何选择按月分组的行
【发布时间】:2018-05-28 21:29:39
【问题描述】:

如何选择按月分组的行。
所以我有一个实体:

public class Security
{
    public Guid Id { get; set; }

    public string Name { get; set; }

    public string Quatation { get; set; }

    public SecurityType SecurityType { get; set; }

    public double Denomination { get; set; }

    public CurrencyType DemoniationType { get; set; }

    public virtual ICollection<ReportPeriod> ReportPeriods { get; set; }
}

报告期实体:

 public class ReportPeriod
{
    public Guid Id { get; set; }

    public DateTime Start { get; set; }

    public DateTime End { get; set; }

    public Guid SecurityId { get; set; }

    public Guid StockExchangeId { get; set; }

    public double Amount { get; set; }

    public virtual Security Security { get; set; }
}

因此,我需要以某种方式获取 ReportPeriod 一年中每个月的一般金额。有没有人有一些想法如何做到这一点?

【问题讨论】:

  • StartEnd 属性是否分别表示月份的开始日期和月份的结束日期(如 2018-01-01 00:00:00 和 2018-01-31 23:59:59 )?
  • @user1672994 不,例如可以是 2-3 天的范围。不知何故,我需要像一月份那样收集:***金额
  • @Jorge 的开始和结束范围可以跨月吗?
  • 懒惰(技术上不正确)的替代方案可能是按两个日期的平均值(如果它们相隔几天)按月分组

标签: c# .net linq


【解决方案1】:

我们可以通过使用 LINQ 来做到这一点。请在 C# 中找到以下代码 sn-p。希望能帮助到你。在这里,我们按年和月分组,然后将金额相加。

namespace Solutions
{
    using System;
    using System.Collections.Generic;
    using System.Linq;

    public class Security
    {
        public Guid Id { get; set; }

        public string Name { get; set; }

        public string Quatation { get; set; }

        //public SecurityType SecurityType { get; set; }

        public double Denomination { get; set; }

        //public CurrencyType DemoniationType { get; set; }

        public virtual ICollection<ReportPeriod> ReportPeriods { get; set; }
    }

    public class ReportPeriod
    {
        public Guid Id { get; set; }

        public DateTime Start { get; set; }

        public DateTime End { get; set; }

        public Guid SecurityId { get; set; }

        public Guid StockExchangeId { get; set; }

        public double Amount { get; set; }

        public virtual Security Security { get; set; }
    }

    public class Entities
    {
        public static void Main(string[] args)
        {

            Security security = new Security()
            {
                Id = Guid.NewGuid(),
                Denomination = 1,
                Name = "A",
                Quatation = "Z",
                ReportPeriods = new List<ReportPeriod>()
            };
            security.ReportPeriods.Add(new ReportPeriod()
            {
                Amount = 10,
                Security = security,
                SecurityId = security.Id,
                End = DateTime.Now.AddDays(1),
                Start = DateTime.Now,
                Id = Guid.NewGuid(),
                StockExchangeId = Guid.NewGuid()
            });
            security.ReportPeriods.Add(new ReportPeriod()
            {
                Amount = 5,
                Security = security,
                SecurityId = security.Id,
                End = DateTime.Now.AddDays(1),
                Start = DateTime.Now,
                Id = Guid.NewGuid(),
                StockExchangeId = Guid.NewGuid()
            });
            security.ReportPeriods.Add(new ReportPeriod()
            {
                Amount = 5,
                Security = security,
                SecurityId = security.Id,
                End = DateTime.Now.AddDays(1),
                Start = DateTime.Now.AddMonths(-1),
                Id = Guid.NewGuid(),
                StockExchangeId = Guid.NewGuid()
            });

            foreach (var groupedReportValues in security.ReportPeriods
                .GroupBy(period => new { period.Start.Year, period.Start.Month }).Select(
                    groupedOnMonth => new
                    {
                        StartYear = groupedOnMonth.Key.Year,
                        StartMonth = groupedOnMonth.Key.Month,
                        AmountSum = groupedOnMonth.Sum(reportValue => reportValue.Amount)
                    }))
            {
                Console.WriteLine(groupedReportValues.StartYear);
                Console.WriteLine(groupedReportValues.StartMonth);
                Console.WriteLine(groupedReportValues.AmountSum);
                Console.WriteLine();
            }

            Console.ReadLine();
        }
    }
}

【讨论】:

  • 目前,我假设我们需要基于 StartDate 的数据,并相应地添加了分组逻辑。
【解决方案2】:

你想要一般的月份金额。

  • 假设您希望它采用 Dictionary&lt;DateTime, double&gt; 格式,其中 Key 是月份的第一个日期(我们在 Value 中有一般金额)。
  • 假设startend 的范围不跨月。

将此属性添加到您的 Security 类中。

public Dictionary<DateTime, double> AmountGroupedByMonth
{
  get
  {
     Dictionary<DateTime, double> table = new Dictionary<DateTime, double>();

     if (ReportPeriods != null && ReportPeriods.Count > 0)
     {
         ReportPeriod frtReportPeriod = ReportPeriods.First();

         DateTime monthStDt = 
             new DateTime(frtReportPeriod.Start.Year, frtReportPeriod.Start.Month, 1);
         double groupedAmount = 0;

         foreach (ReportPeriod reportPeriod in ReportPeriods)
         {
             //Checking if this report should be grouped with pervious report or not
             if (monthStDt.Year == reportPeriod.Start.Year 
                 && monthStDt.Month == reportPeriod.Start.Month)
             {
                 groupedAmount += reportPeriod.Amount;
             }
             else
             {
                 //if we find that this report is of different month.
                 table.Add(monthStDt, groupedAmount);

                 groupedAmount = reportPeriod.Amount;
                 monthStDt = 
                     new DateTime(reportPeriod.Start.Year, reportPeriod.Start.Month, 1);
             }
         }
         if (groupedAmount != 0 && !table.ContainsKey(monthStDt))
              table.Add(monthStDt, groupedAmount);
     }
     return table;
  }
}

通过添加此属性,Security 的对象将可以轻松获得按月份分组的数据。而且,由于它没有存储在任何变量中,因此您无需在使用它之前对其进行更新(或生成)。只需调用此属性,它就会使用最新的可用数据按月计算一般金额。

Security s = new Security();

DateTime nowDate = DateTime.Now;
s.ReportPeriods = new List<ReportPeriod>();
for(int i = 0; i <= 70; i = i + 5)
{
  s.ReportPeriods.Add(new ReportPeriod(nowDate.AddDays(i), nowDate.AddDays( i + 3), 200 ));
}

Dictionary<DateTime, double> AmountGroupedByMonth = s.AmountGroupedByMonth;

输出会是这样的:

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-04-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多