c# - 使用 Linq to SQL 生成销售报告

标签 c# linq-to-sql grouping sum

我目前有以下代码来生成过去 30 天内的销售报告。我想知道是否可以使用 linq 一步生成此报告,而不是我这里的相当基本的循环。

对于我的要求,每天都需要返回一个值给我,所以如果任何一天没有销售,则返回 0。

任何 Sum linq 示例都没有解释如何包含 where 过滤器,因此我对如何获取最近几天每天的总金额感到困惑,或者如果没有销售则为 0我路过。

感谢您的帮助, 丰富

    //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);
        }
    }

编辑: 约翰内斯的回答是处理我的疑问的好方法。下面是对代码的调整,以使其适用于本示例,以防其他人遇到此问题。这将从 allDays 表执行外部联接,并在当天没有销售时返回 0 值。

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 };

最佳答案

您可以按天对所有数据进行分组,并对这些组进行求和。为了满足每天求和的要求,即使是没有顺序的,您可以加入所有日期的列表,或者简单地使用循环来确保包含所有日期。小提示:如果通过 DateTime.Date 属性进行比较,则无需显式设置时间。

这是使用生成器函数的解决方案(取自 MoreLinq 项目):

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>");
            }


        }
    }
}

关于c# - 使用 Linq to SQL 生成销售报告,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2844839/

相关文章:

c# - 从 C#.NET 中的代码隐藏调用 Javascript 函数

c# - asp.net core TestServer找不到配置

c# - 创建大量对象时内存不足C#

c# - 如何忽略linq查询中的空白元素

Javascript:在不记得最后一场比赛的情况下在正则表达式中反向引用

matlab - 根据一列对矩阵行进行分组

C# 保存大图像

c# - 如何将一串二进制数转换为一串十进制数?

c# - 如何查询查询结果集中所有字段的内容?

java 8 按不同计数分组