EF Linq查询比较多行数据

时间:2012-04-10 12:22:14

标签: linq entity-framework

我想创建一个Linq查询,用于比较单个表中多行的日期。 该表包含轮询Web服务以获取帐户余额数据的数据。不幸的是,轮询间隔不是100%确定性,这意味着每个帐户每天可以有0-1个条目。

对于应用程序,我需要以某种格式重新格式化这些数据(参见下面的输出)。 我包括了样本数据和表格的描述。

任何人都可以帮我处理能产生所需输出的EF Linq查询吗?

表:

id          The account id
balance     The available credits in the account at the time of the measurement
create_date The datetime when the data was retrieved

表名:余额
字段:id(int)
领域:平衡(bigint)
字段:create_date(datetime)

样本数据:

id  balance create_date
3   40  2012-04-02 07:01:00.627 
1   55  2012-04-02 13:41:50.427
2   9   2012-04-02 03:41:50.727
1   40  2012-04-02 16:21:50.027
1   49  2012-04-02 16:55:50.127
1   74  2012-04-02 23:41:50.627
1   90  2012-04-02 23:44:50.427
3   3   2012-04-02 23:51:50.827

3   -10 2012-04-03 07:01:00.627
1   0   2012-04-03 13:41:50.427
2   999 2012-04-03 03:41:50.727
1   50  2012-04-03 15:21:50.027
1   49  2012-04-03 16:55:50.127
1   74  2012-04-03 23:41:50.627
2   -10 2012-04-03 07:41:50.727
1   100 2012-04-03 23:44:50.427
3   0   2012-04-03 23:51:50.827

预期产量:

id 帐户ID
日期 用于在行中生成日期的数据组件
balance_last_measurement 最后一次测量日期的余额
差异 日期的第一次和最后一次测量之间的平衡差异

  • 在2012-04-02 id 2中只有1个测量值,它将差值设置为等于最后一个(也是唯一的)测量值。
id      date            balance_last_measurement     difference
1       2012-04-02      90                           35
1       2012-04-03      100                          10
2       2012-04-02      9                            9
2       2012-04-03      -10                         -19
3       2012-04-02      3                           -37
3       2012-04-03      0                            37

更新2012-04-10 20:06

RaphaëlAlthaus的回答非常好,但我确实在原始请求中犯了一个小错误。 “预期产出”中的差异字段应为:

  1. 前一天的最后一次测量与当天的最后一次测量之间的差异
  2. 如果没有前一天,则应使用当天的第一次测量和最后一次测量
  3. 这有可能吗?这似乎很复杂?

2 个答案:

答案 0 :(得分:1)

我会尝试这样的事情。

var query = db.Balances
                .OrderBy(m => m.Id)
                .ThenBy(m => m.CreationDate)
                .GroupBy(m => new
                                  {
                                      id = m.Id,
                                      year = SqlFunctions.DatePart("mm", m.CreationDate),
                                      month = SqlFunctions.DatePart("dd", m.CreationDate),
                                      day = SqlFunctions.DatePart("yyyy", m.CreationDate)
                                  }).ToList()//enumerate there, this is what we need from db
                .Select(g => new
                                 {
                                     id = g.Key.id,
                                     date = new DateTime(g.Key.year, g.Key.month, g.Key.day),
                                     last_balance = g.Select(m => m.BalanceValue).LastOrDefault(),
                                     difference = (g.Count() == 1 ? g.First().BalanceValue : g.Last().BalanceValue - g.First().BalanceValue)
                                 });    

答案 1 :(得分:0)

嗯,一个可能没有优化的解决方案,但只是看看它是否有效。

首先,我们创建一个结果类

public class BalanceResult
    {
        public int Id { get; set; }
        public DateTime CreationDate { get; set; }
        public IList<int> BalanceResults { get; set; }
        public int Difference { get; set; }

        public int LastBalanecResultOfDay {get { return BalanceResults.Last(); }}
        public bool HasManyResults {get { return BalanceResults != null && BalanceResults.Count > 1; }}
        public int DailyDifference { get { return HasManyResults ? BalanceResults.Last() - BalanceResults.First() : BalanceResults.First(); } }

    }

然后我们改变了一点我们的查询

var query = db.Balances
                .GroupBy(m => new
                                  {
                                      id = m.Id,
                                      year = SqlFunctions.DatePart("mm", m.CreationDate),
                                      month = SqlFunctions.DatePart("dd", m.CreationDate),
                                      day = SqlFunctions.DatePart("yyyy", m.CreationDate)
                                  }).ToList()//enumerate there, this is what we need from db
                .Select(g => new BalanceResult
                                 {
                                     Id = g.Key.id,
                                     CreationDate = new DateTime(g.Key.year, g.Key.month, g.Key.day),
                                     BalanceResults = g.OrderBy(l => l.CreationDate).Select(l => l.BalanceValue).ToList()
                                 }).ToList(); 

最后

foreach (var balanceResult in balanceResults.ToList())
            {
                var previousDayBalanceResult = balanceResults.FirstOrDefault(m => m.Id == balanceResult.Id && m.CreationDate == balanceResult.CreationDate.AddDays(-1));
                balanceResult.Difference = previousDayBalanceResult != null ? balanceResult.LastBalanecResultOfDay - previousDayBalanceResult.LastBalanecResultOfDay : balanceResult.DailyDifference;
            }

如所示,性能(例如使用字典),代码可读性当然应该得到改善,但......这就是想法!