我如何重构一个查询,我按照它与另一个表的关系对产品进行排序

时间:2015-12-24 14:51:33

标签: sql postgresql rails-activerecord arel

我有这个查询似乎在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方法。幸运的是,我发现了如何对一系列哈希进行分页。

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

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 )

1 个答案:

答案 0 :(得分:2)

我并不确切地知道您在使用其他工具和/或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