Verwenden Sie Linq to SQL Umsatzbericht zu generieren

stimmen
2

Im Moment habe ich den folgenden Code einen Umsatzbericht über die letzten 30 Tage zu erzeugen. Ich würde gerne wissen, ob es möglich wäre, Linq zu verwenden, um diesen Bericht in einem Schritt zu erzeugen, statt dem eher einfach Schleife ich hier habe.

Für meine Anforderung muss jeden Tag einen Wert für mich zurück, so, wenn es keine Verkäufe für jeden Tag sind dann eine 0 zurückgegeben.

Jede der Summe Linq Beispiele da draußen nicht erklären, wie es möglich wäre, eine enthalten, in dem Filter, so ich bin verwirrt, wie die Gesamtmenge pro Tag zu bekommen, oder eine 0, wenn keine Verkäufe, für die letzten Tage, die ich durchlaufen .

Danke für Ihre Hilfe, Reich

    //setup date ranges to use
    DateTime startDate = DateTime.Now.AddDays(-29);
    DateTime endDate = DateTime.Now.AddDays(1);
    TimeSpan startTS = new TimeSpan(0, 0, 0);
    TimeSpan endTS = new TimeSpan(23, 59, 59);

    using (var dc = new DataContext())
    {
        //get database sales from 29 days ago at midnight to the end of today
        var salesForDay = dc.Orders.Where(b => b.OrderDateTime > Convert.ToDateTime(startDate.Date + startTS) && b.OrderDateTime <= Convert.ToDateTime(endDate.Date + endTS));

        //loop through each day and sum up the total orders, if none then set to 0
        while (startDate != endDate)
        {
            decimal totalSales = 0m;
            DateTime startDay = startDate.Date + startTS;
            DateTime endDay = startDate.Date + endTS;
            foreach (var sale in salesForDay.Where(b => b.OrderDateTime > startDay && b.OrderDateTime <= endDay))
            {
                totalSales += (decimal)sale.OrderPrice;
            }

            Response.Write(From Date:  + startDay +  - To Date:  + endDay + . Sales:  + String.Format({0:0.00}, totalSales) + <br>);

            //move to next day
            startDate = startDate.AddDays(1);
        }
    }

EDIT: Johannes Antwort war eine gute Möglichkeit, meine Frage zu behandeln. Im Folgenden finden Sie eine Anpassung an den Code für dieses Beispiel für den Fall, jemand zum Laufen zu bringen sonst dieses Problem hat. Dies wird eine äußere Verknüpfung aus der Alldays Tabelle durchführen und 0 Werte zurück, wenn es keine Verkäufe für diesen Tag ist.

var query = from d in allDays
                    join s in salesByDay on d equals s.Day into j
                    from s in j.DefaultIfEmpty()
                    select new { Day = d, totalSales = (s != null) ? s.totalSales : 0m };
Veröffentlicht am 16/05/2010 um 19:03
quelle vom benutzer
In anderen Sprachen...                            


2 antworten

stimmen
4

Sie können Gruppe all Ihre Daten bei Tag und Laufe Summe über diese Gruppen. Um das Erfordernis, eine Summe für jeden Tag zu erfüllen, auch diejenigen ohne Ordnung, können Sie entweder beitreten eine Liste aller Daten oder einfach eine Schleife verwenden , um sicherzustellen , dass alle Daten enthalten sind. Kleiner Tipp: Sie brauchen nicht die Zeiten explizit einrichten, wenn Sie durch den Vergleich DateTime.DateEigenschaften.

Hier ist die Lösung, die eine Generatorfunktion (aus dem MoreLinq Projekt) unter Verwendung von:

public static partial class MoreEnumerable
{

    public static IEnumerable<TResult> GenerateByIndex<TResult>(Func<int, TResult> generator)
    {
        // Looping over 0...int.MaxValue inclusive is a pain. Simplest is to go exclusive,
        // then go again for int.MaxValue.
        for (int i = 0; i < int.MaxValue; i++)
        {
            yield return generator(i);
        }
        yield return generator(int.MaxValue);
    }

}

public class MyClass
{
    private void test()
    {
        DateTime startDate = DateTime.Now.AddDays(-29);
        DateTime endDate = DateTime.Now.AddDays(1);

        using (var dc = new DataContext())
        {
            //get database sales from 29 days ago at midnight to the end of today
            var salesForPeriod = dc.Orders.Where(b => b.OrderDateTime > startDate.Date  && b.OrderDateTime <= endDate.Date);

            var allDays = MoreEnumerable.GenerateByIndex(i => startDate.AddDays(i)).Take(30);

            var salesByDay = from s in salesForPeriod
                        group s by s.OrderDateTime.Date into g
                        select new {Day = g.Key, totalSales = g.Sum(x=>(decimal)x.OrderPrice};

            var query = from d in allDays
                        join s in salesByDay on s.Day equals d
                        select new {Day = s.Day , totalSales = (s != null) ? s.totalSales : 0m;


            foreach (var item in query)
            {
                Response.Write("Date: " +item.Day.ToString() " Sales: " + String.Format("{0:0.00}", item.totalSales) + "<br>");
            }


        }
    }
}
Beantwortet am 16/05/2010 um 20:00
quelle vom benutzer

stimmen
0

Ich denke, dass, wenn Ihre Aufzählung für einen Tag keine Daten enthält, können Sie keine Werte für diesen Tag zurückkehren können. Das Beste, was ich denken kann, ist eine Liste der Bestell Objekte mit einem Nullwert für jeden Tag zu schaffen und eine Vereinigung mit dem Ergebnis der Abfrage zu erstellen. Hier ist, was ich kam mit. Aber ich denke, durch jede Gruppe Looping, zu überprüfen, ob jeder Tag „übersprungen“, und Null für jeden Tag der Rückkehr, die „übersprungen“ wird, ist einfacher als die eigene Aufzählung im Speicher zu schaffen (es sei denn Sie eine Aufzählung mit den „fehlenden Lücken wollen " ausgefüllt). Bitte beachten Sie, dass ich, dass für jede Gruppe im Grunde gehe davon aus, Sie alle Werte für einen einzigen Tag summieren möchten.

List<Order> zeroList = new List<Order>();
while (startDate <= endDate)
{
  zeroList.Add(new Order { OrderDateTime = startDate, OrderPrice = 0 });
  startDate = startDate.AddDays(1)
}

var comboList = zeroList.Union(dc.Orders.Where(b => b.OrderDateTime > Convert.ToDateTime(startDate.Date + startTS) && b.OrderDateTime <= Convert.ToDateTime(endDate.Date + endTS))

var groupedTotalSales = comboList.GroupBy(b => b.OrderDateTime.Date)
  .Select(b => new { StartDate = Convert.ToDateTime(b.Key + startTS), EndDate = Convert.ToDateTime(b.Key + endTS), Sum = b.Sum(x => x.OrderPrice });

foreach (totalSale in groupedTotalSales)
  Response.Write("From Date: " + totalSale.StartDate + " - To Date: " + totalSale.EndDate + ". Sales: " + String.Format("{0:0.00}", (decimal)totalSale.Sum) + "<br/>");
Beantwortet am 16/05/2010 um 19:27
quelle vom benutzer

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more