【问题标题】:linq groupby() and Sum()linq groupby() 和 Sum()
【发布时间】:2016-05-17 12:42:00
【问题描述】:

这可能很微不足道,但我无法让它工作(linq 级别的新手)。

我想对同一天的客户的行进行分组和求和(日期显示在 epoc/unixtime 中)。

目前它只是将最大值显示为 21(从 Kbytes 转换为 Gbytes),而不是我想要看到的 ±26。

如何添加 GroupBySum 子句以添加每天的千字节?

public class Images
{
    public string ClientName { get; set; }
    public string ImageID { get; set; }
    public int PolicyType { get; set; }
    public int ScheduleType { get; set; }
    public Int64 BackupTime { get; set; }
    public Int64 KBytes { get; set; }
}

public static List<Images> images = new List<Images>();

    public void calc()
    {

        foreach (var client in clients)
        {
            totalmax = 0;
            totalavg = 0;
            foreach (var ptype in ptypes)
            {

                var windowsquery = images
                    .Where(s => s.PolicyType == Convert.ToInt16(ptype) && s.ScheduleType == 0 && s.ClientName == client)
                    .Select(s => s.KBytes);

                double typemax = windowsquery.DefaultIfEmpty().Max()/1048576;
                totalmax = Math.Round(totalmax + typemax);
                double typeavg = windowsquery.DefaultIfEmpty().Average()/1048576;
                totalavg = Math.Round(totalavg + typeavg);

            }
            Console.WriteLine("Client = {0}, Max = {1}, Ave = {2}", client,totalmax, totalavg);
            Console.ReadKey();
        }
    }

输出(从输出中省略其他客户端)

Client = Client2,Max = 21,Ave = 14

更新:实现了这个

var summary = (from image in images
                           where image.ScheduleType == 0
                           group image by new
                           {
                               image.ClientName,
                               image.PolicyType,
                               image.ScheduleType,
                               BackupDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0)
                                                                       .AddSeconds(image.BackupTime)
                                                                       .ToString("yyyy-MM-dd")
                           } into imageGroup
                           select new
                           {
                               ClientName = imageGroup.Key.ClientName,
                               PolicyType = imageGroup.Key.PolicyType,
                               BakupDateTime = imageGroup.Key.BackupDateTime,
                               SumGBytes = imageGroup.Sum(s => s.KBytes) / 1048576.0,
                               AvgGBytes = imageGroup.Average(s => s.KBytes) / 1048576.0,

                           }
                                    ).ToList();

但总和不正确,平均值工作正常。

【问题讨论】:

  • 此输入是否包含 Client1 和 Client2 的所有记录?如果是这样,那么 Client2 的最大值是 ~21,而不是 ~26。你为什么要 26 岁?
  • 是的,这个示例输入是正确的。因为日期(1463234422 & 1463234420)是同一天。我想要一天总和的大小
  • 好吧,你是对的,我以前没有注意到这一点。

标签: c# linq group-by


【解决方案1】:

检查这个:

var summary = (from image in images
               group image by new { image.ClientName, 
                                    image.PolicyType,
                                    BackupDateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0)
                                                .AddSeconds(image.BackupTime)
                                                .ToString("MM/dd/yyyy", CultureInfo.InvariantCulture)
                                  } into imageGroup
               select new { ClientName = imageGroup.Key.ClientName, 
                            PolicyType = imageGroup.Key.PolicyType,
                            BakupDateTime = imageGroup.Key.BackupDateTime,
                            SumGBytes = imageGroup.Sum(s => s.KBytes) / 1048576.0,
                            AvgGBytes = imageGroup.Average(s => s.KBytes) / 1048576.0,
                            MaxGBytes = imageGroup.Max(s => s.KBytes) / 1048576.0,
                            Records = imageGroup.Count()
                          }
              ).ToList();

您可以使用以下查询列出所有已转换 BackupTime 的记录:

var listWithDateTime = (from image in images
                        orderby image.ClientName ascending, 
                                image.PolicyType ascending, 
                                image.BackupTime ascending
                        select new { 
                                 ClientName = image.ClientName,
                                 PolicyType = image.PolicyType,
                                 GBytes = image.KBytes / 1048576.0,
                                 UnixTimestamp = image.BackupTime,
                                 NormalDate = new DateTime(1970, 1, 1, 0, 0, 0, 0)
                                            .AddSeconds(image.BackupTime)
                                            .ToString("MM/dd/yyyy", CultureInfo.InvariantCulture) 
                               }
                       ).ToList();

【讨论】:

  • 谢谢。它生成的总和不正确,但平均值是正确的。我已经将输入输入到excel中并逐行验证。
  • 您能否提供一个错误总和的例子,例如:[日期]、[客户]、[正确总和]、[错误总和]
  • 在我上传的图片中,您会看到在控制台输出中显示平均值,并且与 Excel 中列出的内容相匹配。在大多数情况下,每天只有 1 个实例,因此平均值 = 总数。对于少数情况,有 2 个实例在控制台中列出的平均值等于总数的 50%。
  • 我稍微修改了我的 linq 查询 - 添加了 RecordsMaxGBytes。您能否再次运行此查询并检查每个组返回的 Records 值是否等于 Excel 中的数量?
  • 我相信有些记录是重复的。我添加了一个帮助查询 listWithDateTime - 试试这个并检查是否有重复。
【解决方案2】:

好像是重复发帖,Stack Overflow 中已经有答案了...

var windowsquery = images
                .Where(s => s.PolicyType == Convert.ToInt16(ptype) && s.ScheduleType == 0 && s.ClientName == client).GroupBy(s => YourDateField)
                .Select(s => s.Sum(i => i.KBytes));

 var windowsquery = images
                        .Where(s => s.PolicyType == Convert.ToInt16(ptype) && s.ScheduleType == 0 && s.ClientName == client).GroupBy(s => YourDateField)
                        .Select(g=>new { sum = g.Sum(k=>k.KBytes), field = g.Key });

【讨论】:

    【解决方案3】:

    你已经试过这个了吗?

     var windowsquery = images
                        .Where(s => s.PolicyType == Convert.ToInt16(ptype) 
                         && s.ScheduleType == 0 && s.ClientName == client)
                        .GroupBy(s => s.date)
                        .Select(s => s.Sum(y=>y.KBytes));
    

    在您添加的图片中,日期似乎不正确还是特殊格式?

    【讨论】:

    • 嗨,日期是 unix 时间(从 1970/01/01 开始的秒数),但我找到了另一种转换方法。为了测试,我可以尝试让 2 行中的“日期字段”匹配,看看 groupby 是否有效。
    • 我现在试过了,记得我今天早些时候做过。当我将 groupby 放在 select 前面时,Kbytes 变为红色,并显示“名称 Kbytes 在当前上下文中不存在”。如果我删除 groupby,它看起来又很好了。
    • 是的,对不起,我是即时写的,现在更正: Select(s => s.Sum(y=>y.KBytes));我比较习惯查询语法。
    猜你喜欢
    • 1970-01-01
    • 2023-03-30
    • 1970-01-01
    • 2016-06-17
    • 1970-01-01
    • 1970-01-01
    • 2012-04-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多