Получить сумму значений между двумя датами с одинаковыми ссылками на месяц - PullRequest
0 голосов
/ 30 ноября 2018

это моя проблема: я должен суммировать все записи между двумя ежемесячными доходами с одной ссылкой.Пример:

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) должна быть равна всех пожертвований и последующих записейв течение всего года, чтобы отобразить полный годовой отчет.Как это сделать, используя LINQ в C # ?Я использую подход 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 голосов
/ 01 декабря 2018

Новая версия;Я предполагаю, что в начале у вас нет записей «Gift Aid» без суммы.

Я изменил класс 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, где добавленный аргумент оценивается с учетом следующего воскресенья относительно DateTime в объекте Entry.Чтобы присвоить это значение, я использовал следующую функцию

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.Есть только два запроса (вместо двух), потому что теперь мне не нужно вычислять дату для привязки к записи «Gift Aid», связанной с соответствующими пожертвованиями, потому что теперь я построил ее в начале с помощью метода 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");
            }

Повторяю, у меня есть предположение, которое может быть очень уместным: я просил вас сообщить об этом в комментарии, но вы никогда не спрашивали меня.Еще одна проблема может быть тип суммы: в ваших данных это число?Если это строка, у вас могут возникнуть проблемы с суммированием ...

Результат программы отличается от вашего примера, потому что 3, 5 и 7 ноября не на одной неделе, поэтому 3 остается один, покаСуммы 3, 5 суммируются (с суммой 11/11, потому что это на той же неделе 3 и 5).

Надеюсь, это поможет!

0 голосов
/ 01 декабря 2018

Я пытался интерпретировать ваше указание, поэтому я думаю, что вы должны более или менее определить класс записей таким образом

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, где вы держите только частичную сумму (или вы отбрасываете их и удерживаете единичные пожертвования: вам просто нужноОбязательно избегайте двойного учета) и группируйте суммы по дате месяца (это похоже на то, что я делал в списке).

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