首页 > 解决方案 > 使用 PostgreSQL OVERLAPS 方法的 Arel 表

问题描述

让我先承认有几种不同的方法可以完成重叠,但关于这个问题,我特别想弄清楚如何使用实际的PostgreSQL OVERLAPS方法Arel。为此,这个问题更多地与更好地理解 Arel 有关,而不是实现某些版本的重叠功能。

我在用着Rails 5.1

这是我试图在 Arel 中复制的 SQL 语句:

SELECT DISTINCT
  venues.id
FROM
  venues
LEFT OUTER JOIN
  reservations
ON
  venues.id = reservations.venue_id
WHERE (
  (reservations.venue_id IS NULL)
  OR NOT (
    (reservations.start, reservations.end)
    OVERLAPS
    (DATE '2018-09-02', DATE '2018-09-03')
  )
)

我目前有以下确实会生成上述内容:

Venue.arel_table.project(
  Venue.arel_table[:id]
).from(
  Venue.arel_table
).join(
  Reservation.arel_table, Arel::Nodes::OuterJoin
).on(
  Venue.arel_table[:id].eq(Reservation.arel_table[:venue_id])
).where(
 Arel::Nodes::Grouping.new(
    Reservation.arel_table[:venue_id].eq(nil)
  ).or(
    Arel.sql("NOT ((reservations.start, reservations.end) OVERLAPS (DATE '2018-09-02', DATE '2018-09-03'))")
  )
)

但是,我觉得可能有更好的方法来做到这一点;我一直在尝试实现Arel::Nodes::NamedFunctionOVERLAPS但是,当我用Arel.sql以下语句替换上面的语句时,它没有正确执行 SQL:

Arel::Nodes::NamedFunction.new(
  'OVERLAPS',
  [
    Arel::Nodes::SqlLiteral.new('(reservations.start, reservations.end)'),
    Arel::Nodes::SqlLiteral.new("(DATE '2018-09-02', DATE '2018-09-03')")
  ]
) 

结果是

...OVERLAPS ((reservations.start, reservations.end), (DATE '2018-09-02', DATE '2018-09-03'))

OVERLAPS实施with的正确方法是什么Arel

标签: ruby-on-railspostgresqlarel

解决方案


由于OVERLAPS是 SQL 运算符,我相信以下表达式应该有效:

Arel::Nodes::InfixOperation.new(
  'OVERLAPS', 
  Arel::Nodes::SqlLiteral.new('(reservations.start, reservations.end)'),
  Arel::Nodes::SqlLiteral.new("(DATE '2018-09-02', DATE '2018-09-03')"
)

推荐阅读