【问题标题】:How to find a set of missing dates in a table from date range query如何从日期范围查询中查找表中的一组缺失日期
【发布时间】:2023-03-15 04:27:02
【问题描述】:

有一些与我的问题相关的 stackoverflow 帖子,但不是全部相似。

我想要一个高效且有点优雅(如果可能)的解决方案,以便在将用户指定的日期范围与 postgresql 中的汇总表进行比较后获取缺失日期的数组。我知道的一种方法是将范围放入日期列表中,然后通过查询 EXIST 或 if result == nil?/empty? 等单独与所有日期进行比较。但是如果用户要做一个大范围,这可能会消耗资源并且速度很慢。

除了目前列出的方法之外,还有其他方法吗?

谢谢

【问题讨论】:

    标签: ruby-on-rails gaps-and-islands rails-postgresql


    【解决方案1】:

    首先,我们需要对日期进行排序。在 ruby​​ 中,这很简单

    sorted_dates = dates.sort
    

    如果您知道日期已排序,则只需从第一个日期开始,并在您遍历日期范围时递增一个。如果您的数组中的下一个日期不是您预期的日期,请将缺少的日期添加到您的 missing_dates 数组中,并继续递增直到您到达包含的日期。

    此代码可能如下所示:

    def find_missing_dates(sorted_dates)
      current_date = sorted_dates[0]
      missing_dates = Set.new
      sorted_dates.each do |date|
        while current_date != date
          missing_dates << current_date
          current_date += 1.day
        end
        current_date += 1.day
      end
    end
    

    对于一般情况,这是 O(N),因此为了提高效率,我们可以一分为二并递归。

    def dates_between(lower, upper)
      (lower..upper).to_a - [lower,upper]
    end
    
    def find_missing_dates(sorted_dates, missing_dates = Set.new)
        min_date = sorted_dates[0]
        max_date = sorted_dates[-1]
        if (min_date - max_date).to_i == (sorted_dates.count - 1)
          missing_dates
        else
          middle_date_lower = sorted_dates[sorted_dates.count / 2 - 1]
          middle_date_upper = sorted_dates[sorted_dates.count / 2]
          unless (middle_date_upper - middle_date_lower) == 1
            missing_dates.merge(dates_between(middle_date_lower, middle_date_upper))
          end
          find_missing_dates(sorted_dates[0..(sorted_dates.count/2 - 1)], missing_dates).merge(find_missing_dates(sorted_dates[(sorted_dates.count/2)..-1]))
        end
    end
    
    find_missing_dates(sorted_dates)
    

    这仍然是最坏情况 O(N),但平均情况是 O(log N)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-10-05
      • 2021-08-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-03-04
      相关资源
      最近更新 更多