1

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

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

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

桌子:

id 账户编号
balance 计量时账户中的可用额度
create_date 检索数据的日期时间

表名:Balances
字段:id(int)
字段:balance(bigint)
字段:create_date(datetime)

样本数据:

id 余额 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 年 4 月 2 日,id 2 只有 1 个测量值,它将差值设置为最后(也是唯一的)测量值。
id 日期 balance_last_measurement 差异
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ël Althaus 的回答非常好,但我在最初的请求中确实犯了一个小错误。“预期输出”中的差异字段应该是:

  1. 前一天最后一次测量与当天最后一次测量的差值
  2. 如果没有前一天,则应使用当天的第一次测量和最后一次测量

这可能吗?好像很复杂?

4

2 回答 2

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)
                                 });    
于 2012-04-10T14:38:01.453 回答
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;
            }

如前所述,性能(例如字典的使用)、代码可读性当然应该提高,但是……这就是想法!

于 2012-04-10T19:04:52.663 回答