【问题标题】:How do I refactor a query where I sort products by its relationship from another table如何重构查询,在该查询中按产品与另一个表的关系对产品进行排序
【发布时间】:2015-12-24 14:51:33
【问题描述】:

我有这个查询似乎可以在 pgAdmin 中使用。但是,当我尝试将其翻译为使用 scuttle 时,我得到了一个包含整个 case 语句的大量查询片段。如何重构此查询以便在 Arel 中使用它?

SELECT  products.*, case when
(select custom_fields.value_text
        from custom_fields
        where custom_fields.custom_field_definition_id = 4
        and custom_fields.table_record_id = products.id and custom_fields.belongs_to_table = 'product') is null 
then 'stopped'
when
(select custom_fields.value_text
        from custom_fields
        where custom_fields.custom_field_definition_id = 4
        and custom_fields.table_record_id = products.id and custom_fields.belongs_to_table = 'product') is not null 
then (select custom_fields.value_text from custom_fields where custom_fields.custom_field_definition_id = 4
             and custom_fields.table_record_id = products.id and custom_fields.belongs_to_table = 'product')
end as sorted
from products
order by sorted

其他信息:我创建了一个 sqlite 数据库,它显示了预期的行为,可用于进一步的实验。

https://github.com/bigos/rails-sorting/blob/master/README.org

初步结论:我找到了一种获得预期结果的方法,但不能再将它与 Active Record 方法一起使用。幸运的是,我找到了如何对哈希数组进行分页。

最佳解决方案:如果我将代码作为子查询按顺序排列,我可以返回正确的活动记录关系。

SELECT products.*
FROM products
ORDER BY (case when
(select custom_fields.value_text
from custom_fields
where custom_fields.custom_field_definition_id = 4
and custom_fields.table_record_id = products.id and custom_fields.belongs_to_table = 'product') is null 
then 'stopped'
when
(select custom_fields.value_text
from custom_fields
where custom_fields.custom_field_definition_id = 4
and custom_fields.table_record_id = products.id and custom_fields.belongs_to_table = 'product') is not null 
then (select custom_fields.value_text from custom_fields where custom_fields.custom_field_definition_id = 4
and custom_fields.table_record_id = products.id and custom_fields.belongs_to_table = 'product')
end )

【问题讨论】:

  • 请提供源数据和预期输出。
  • 目前我使用了两个查询的联合。我将在两周内进行代码审查,然后我们将决定下一步。
  • 这个似乎工作 ap Product.all.order(%Q|coalesce((SELECT "custom_fields"."value_text" FROM "custom_fields" WHERE ("custom_fields"."table_record_id" = "products "."id" AND "custom_fields"."value_text" IS NOT NULL)), 'stopped') |)

标签: sql postgresql rails-activerecord arel


【解决方案1】:

我不知道您在使用其他工具和/或 Active Record 时遇到了什么问题,但下面的查询应该是等效的并且可能更快:

select p.*, coalesce(cf.value_text, stopped) as sorted
from
    products p
    left outer join custom_fields cf
        on      cf.table_record_id = p.id
            and cf.belongs_to_table = 'product'
            and cf.custom_field_definition_id = 4
order by sorted

这种类型的查询是最好避免使用这类“自定义字段”表的原因之一。

另一个非常接近原始方法的替代方法是在coalesce 中使用标量子查询。您甚至可能更喜欢这种方式,因为如果子查询通过某种方式返回多个值,则会导致错误。

select
    p.*,
    coalesce(
        (
        select custom_fields.value_text
        from custom_fields cf
        where 
                f.table_record_id = p.id
            and cf.custom_fields.belongs_to_table = 'product'
            and cf.custom_field_definition_id = 4
        ),
        'stopped'
    ) as sorted
from products p
order by sorted

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多