获取两个具有相同月份参考的日期之间的值之和

时间:2018-11-30 18:38:31

标签: c# linq linq-to-sql

这是我的问题: 我必须将两个月收入之间的所有条目加起来,并使用相同的参考。 示例:

Month 1
Payment Date  Ref          Amount
03/11/2018  donations1     £  10
05/11/2018  donations2     £  90
07/11/2018  donations3     £ 100
01/11/2018  Gift Aid       £ 200  (Needs to be the sum of donations)

11/11/2018  donation4      £ 30
12/11/2018  donations5     £ 20
10/11/2018  Gift Aid       £ 50   (Needs to be the sum of donations)

所有捐赠之间,捐赠(1,2,3)的总和必须等于所有捐赠及其全年的后续输入,以便显示全年报告。 如何使用C#中的 LINQ 执行此操作? 我正在使用MVC方法。

从Gufus提取的代码已调整为我的代码(非常有用!),但仍然不是我想要的。

var listGaDonations = db.Upload
                .Where(x => x.IsGiftAid == true)
                .ToList();

            var list = from e in listGaDonations
                where e.FirstName != "Gift Aid"
                       group e.Amount by e.Ref
                into p
                select new
                {
                    Ref = p.Key,
                    Amount = p.Sum()
                };
            var listJoined = from p in list
                join e in listGaDonations on p.Ref equals e.Ref
                group e.PaymentDate by p
                into a
                select new
                {
                    a.Key.Ref,
                    a.Key.Amount,
                    PaymentDate = a.Max()
                };
            foreach (var p in listJoined)
            {
                Upload e = new Upload(p.Ref, "Gift Aid", p.PaymentDate, p.Amount);
                listGaDonations.Add(e);
            }

            var sortentries = from e in listGaDonations
                orderby e.Ref, e.PaymentDate
                select e;

            var test = sortentries.Where(x => x.PaymentDate != DateTime.MinValue).ToList();

            return View(test);

我得到的结果:

 Ref:      Donation    Payment Date    Amount
CIZ3S42J    don1        19/08/2018     £100.00
EG066AUM    don2        01/08/2018     £123.00
EUGOP7T9    don3        04/09/2018     £55.00
GRMEV47F    Gift Aid    02/09/2018     £xxx   (Which is not the sum of 
                                                donations)

有人可以帮助我,提前感谢您的支持。

2 个答案:

答案 0 :(得分:0)

我试图解释您的指示,所以我认为您必须以这种方式或多或少地定义条目的类别

public class Entry
    {
        private int _reference; 
        private string _donation;
        private DateTime _date;
        private double _amount;

        public Entry(int aReference, string aDonation, DateTime aDate, double aAmount)
            {
                _reference = aReference;
                _donation = aDonation;
                _date = aDate;
                _amount = aAmount;
            }

        public double Amount
        {
            get { return _amount; }
            set { _amount = value; }
        }

        public DateTime Date
        {
            get { return _date; }
            set { _date = value; }
        }

        public string Donation
        {
            get { return _donation; }
            set { _donation = value; }
        }

        public int Reference 
        {
            get { return _reference; }
            set { _reference = value; }
        }
}

我敢肯定会有更聪明的编写程序的方法,但是以下方法似乎可行

List<Entry> entries = new List<Entry>();

            entries.Add(new Entry(1, "donation 1", new DateTime(2018, 11, 3), 10));
            entries.Add(new Entry(1, "donation 2", new DateTime(2018, 11, 5), 90));
            entries.Add(new Entry(1, "donation 3", new DateTime(2018, 11, 7), 100));
            entries.Add(new Entry(2, "donation 4", new DateTime(2018, 11, 11), 30));
            entries.Add(new Entry(2, "donation 5", new DateTime(2018, 11, 12), 20));

            var list = from e in entries
                       where e.Donation != "partial total"
                       group e.Amount by e.Reference into p
                       select new
                       {
                           Reference = p.Key,
                           Amount = p.Sum()
                       };

            var listjoined = from p in list
                             join e in entries on p.Reference equals e.Reference
                             group e.Date by p into a
                             select new
                             {
                                 Reference = a.Key.Reference,
                                 Amount = a.Key.Amount,
                                 Date = a.Max()
                             };


            foreach(var p in listjoined)
            {
                Entry e = new Entry(p.Reference, "partial total", p.Date, p.Amount);
                entries.Add(e);
            }
            var sortedentries = from e in entries
                                orderby e.Reference, e.Date
                                select e;

            foreach(var e in sortedentries)
            {
                Console.WriteLine($"{e.Reference}; {e.Donation} occurred on {e.Date}; the amount is of {e.Amount} USD");
            }

如果您希望按月总计,则只需在其中仅保留部分总计(或丢弃它们并进行单次捐赠:您只需确保避免重复计算)的地方放一个where子句,然后将金额分组即可月日期(这与我在列表中所做的操作类似)。

答案 1 :(得分:0)

新版本;我的假设是,一开始您就没有“赠金”记录。

我修改了Entry类,只是更改了Reference(它是字符串而不是int)

public class Entry
    {
        private string _reference; 
        private string _donation;
        private DateTime _date;
        private double _amount;

        public Entry(string aReference, string aDonation, DateTime aDate, double aAmount)
            {
                _reference = aReference;
                _donation = aDonation;
                _date = aDate;
                _amount = aAmount;
            }

        public double Amount
        {
            get { return _amount; }
            set { _amount = value; }
        }

        public DateTime Date
        {
            get { return _date; }
            set { _date = value; }
        }

        public string Donation
        {
            get { return _donation; }
            set { _donation = value; }
        }

        public string Reference 
        {
            get { return _reference; }
            set { _reference = value; }
        }

        }

我添加了一个从Entry派生的类,即Entry2:

public class Entry2:Entry
    {
        private DateTime _date2;

        public Entry2(string aReference, string aDonation, DateTime aDate, double aAmount, DateTime aDate2)
        :base(aReference, aDonation, aDate, aAmount)
        {
            _date2 = aDate2;
        }

        public DateTime Date2
        {
            get { return _date2; }
            set { _date2 = value; }
        }
    }

Entry2的DateTime字段多于Entry;您的数据采用Entry的形式,我将它们转换为Entry2对象,在其中添加的参数按照对象Entry中的DateTime的以下星期日进行了赋值。要分配此值,我使用了以下功能

public static DateTime NextSunday(DateTime aDate)
        {

            if (aDate.DayOfWeek.ToString() == "Monday") { return aDate.AddDays(6); }
            else if (aDate.DayOfWeek.ToString() == "Tuesday") { return aDate.AddDays(5); }
            else if (aDate.DayOfWeek.ToString() == "Wednesday") { return aDate.AddDays(4); }
            else if (aDate.DayOfWeek.ToString() == "Thursday") { return aDate.AddDays(3); }
            else if (aDate.DayOfWeek.ToString() == "Friday") { return aDate.AddDays(2); }
            else if (aDate.DayOfWeek.ToString() == "Saturday") { return aDate.AddDays(1); }
            else { return aDate; }
        }

最后...程序!您可以看到我按新的DateTime字段分组。只有两个查询(而不是两个),因为现在我不需要计算与关联到各个捐赠的“礼物援助”条目关联的日期,因为现在我是使用NextSunday方法开始构建的

List<Entry> entries = new List<Entry>();

            entries.Add(new Entry("d1", "donation 1", new DateTime(2018, 11, 3), 10));
            entries.Add(new Entry("d2", "donation 2", new DateTime(2018, 11, 5), 90));
            entries.Add(new Entry("d3", "donation 3", new DateTime(2018, 11, 7), 100));
            entries.Add(new Entry("d4", "donation 4", new DateTime(2018, 11, 11), 30));
            entries.Add(new Entry("d5", "donation 5", new DateTime(2018, 11, 12), 20));

            List<Entry2> entries2 = new List<Entry2>();
            foreach(var e in entries) 
            {
                entries2.Add(new Entry2(e.Reference, e.Donation, e.Date, e.Amount, NextSunday(e.Date)));
            }

            var list = from e in entries2
                       where e.Donation != "Gift Aid"
                       group e.Amount by e.Date2 into p
                       select new
                       {
                           Date2 = p.Key,
                           Amount = p.Sum()
                       };
foreach(var p in list)
            {
                Entry e = new Entry("Some code", "Gift Aid", p.Date2, p.Amount);
                entries.Add(e);
            }
            var sortedentries = from e in entries
                                orderby e.Date
                                select e;

            foreach(var e in sortedentries)
            {
                Console.WriteLine($"{e.Reference}; {e.Donation} occurred on {e.Date}; the amount is of {e.Amount} USD");
            }

我再说一遍,我认为这可能是非常相关的:我已经在评论中问过您有关此方面的信息,但您从未问过我。金额的类型可能还有一个问题:您的数据中是数字吗?如果是字符串,则求和可能会遇到问题...

程序的结果与您的示例不同,因为11月3日,5月7日和7月7日不在同一周,这就是为什么3个单独存在而3、5的数量相加的原因(还有11/11的数量,因为在3和5的同一周)。

希望有帮助!