【问题标题】:Find overlapping seasons where seasons have_many date_ranges查找季节有_many date_ranges 的重叠季节
【发布时间】:2012-03-05 17:10:44
【问题描述】:

我有以下设置:

class Season < AR::Base
  has_many :date_ranges
end

class DateRange < AR::Base
  # has a :starts_at & :ends_at
end

如何从季节实例中找到所有重叠的季节?我已经尝试了几个不同的查询(如下)。但是我一直遇到的问题是,即时检查的季节也可能有多个 date_ranges。我可以用循环解决它,但我宁愿只使用查询。

此查询查找所有重叠的季节,但它仅针对 1 个输入 date_range Season.joins(:date_ranges).where("starts_at &lt;= ? AND ends_at &gt;= ?", ends_at, starts_at)

也许我需要一些东西来为实例上的每个 date_range 链接几个 OR,但 where() 只使用 AND。

所以简而言之,找到重叠不是问题,但是我如何找到多个 date_range 与整个数据库的重叠?

【问题讨论】:

  • MySQL 但如果可能的话,我也希望它与其他人兼容

标签: ruby-on-rails ruby activerecord arel


【解决方案1】:

最简单的方法是通过直接的 SQL。像这样的:

DateRange.find_by_sql(%q{
    select a.*
    from date_ranges a
    join date_ranges b on
            a.id < b.id
        and (
               (a.ends_at   >= b.starts_at and a.ends_at   <= b.ends_at)
            or (a.starts_at >= b.starts_at and a.starts_at <= b.ends_at)
            or (a.starts_at <= b.starts_at and a.ends_at   >= b.ends_at)
        )
    where season_id = ?
}, season_id)

基本思想是将表连接到自身,以便您可以轻松地比较范围。 a.id &lt; b.id 用于获得独特的结果并过滤掉“范围匹配自身”的情况。内部or 条件检查两种类型的重叠:

[as-----ae]            [as-----ae]    
    [bs-----be]    [bs-----be]

[as--------------ae]         [as----ae]
     [bs----be]         [bs--------------be]

您可能需要考虑端点,如果两个间隔仅在端点匹配,则该查询认为两个间隔重叠,这可能不是您想要的。

大概您已经对 (season_id, starts_at, ends_at) 三元组有一个唯一约束,并且大概您已经确保 starts_at &lt;= ends_at

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-11
    • 2023-03-24
    • 2012-03-18
    • 2012-08-12
    • 1970-01-01
    • 2021-06-17
    • 2013-11-06
    相关资源
    最近更新 更多