【问题标题】:Activerecord or Raw SQLActiverecord 或原始 SQL
【发布时间】:2017-05-22 14:18:14
【问题描述】:

我有一些 RAW sql,但我不确定作为 Activerecord 调用是否会更好,或者我应该使用 RAW sql。这会很容易转换为 AR 吗?

select  *
from    logs t1
where
  log_status_id = 2 and log_type_id = 1
        and not exists
        (
        select  *
        from    logs t2
        where   t2.log_version_id = t1.log_version_id
                and t2.log_status_id in (1,3,4)
                and log_type_id = 1
        )
ORDER BY created_at ASC

所以是这样的?:

Log.where(:log_status_id=>2, log_type_id => 1).where.not(Log.where.....)

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:

    您可以使用 AREL 做到这一点。示例见Rails 3: Arel for NOT EXISTS?

    不过,我个人经常发现原始 SQL 比 AREL 查询更具可读性/可维护性。而且我猜大多数开发人员通常也更熟悉它。

    但无论如何,您将log_states_idlog_type_id 的缩小范围与子查询分开的方法是一个好主意。即使您的 .where.not 构造不会像所写的那样工作。

    这应该可以解决问题:

    Log.where(log_status_id: 2, log_type_id: 1)
       .where("NOT EXISTS (
        select *
        from    logs t2
        where   t2.log_version_id = logs.log_version_id
                and t2.log_status_id in (1,3,4)
                and t2.log_type_id = logs.log_type_id)")
       .order(:created_at)
    

    这可能会出现问题的唯一情况是当您尝试将此查询连接到其他查询时,因为外部表可能会收到与 logs 不同的别名。

    【讨论】:

    • NOT EXISTS 在 where 中的外观如何?我想我不会有 t2, t1 ?
    • 主表通常(这就是我添加警告最后一句的原因)保留其名称,以便您可以从子查询中引用它。我更新了答案以显示完整的查询。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-11
    • 2019-08-18
    • 2014-10-09
    • 1970-01-01
    • 2023-03-27
    相关资源
    最近更新 更多