Postgres选择一个concat字段并在Rails中ILIKE它

Nat*_*ert 4 sql postgresql ruby-on-rails

很简单,试图这样做

 SELECT  (artist_name || ' ' || name) as full_name FROM "songs"  WHERE "songs"."working" = 't' AND (full_name ILIKE('%Jack Beats%')) AND (full_name ILIKE('%Epidemic%')) AND (full_name ILIKE('%Dillon Francis%')) ORDER BY songs.published_at asc LIMIT 1
Run Code Online (Sandbox Code Playgroud)

但我明白了

ActiveRecord::StatementInvalid: PG::Error: ERROR:  column "full_name" does not exist
Run Code Online (Sandbox Code Playgroud)

我已经尝试在站点之前添加表名,但没有效果.

mu *_*ort 9

正如在注释中提到的那样,您不能在WHERE子句中引用SELECT中的别名.您可以使用派生表作为dwurf建议,但Rails中的派生表有点乱.您可以在WHERE中扩展连接:

Song.where(:working => true)
    .where("artist_name || ' ' || name ILIKE ?", '%Jack Beats%')
    .where("artist_name || ' ' || name ILIKE ?", '%Epidemic%')
    .where("artist_name || ' ' || name ILIKE ?", '%Dillon Francis%')
    .order('songs.published_at asc')
    .limit(1)
Run Code Online (Sandbox Code Playgroud)

如果你做了很多这样的事情,命名范围可能会有用:

class Song < ActiveRecord::Base
    #...
    def self.full_name_like(name)
        where("artist_name || ' ' || name ILIKE ?", "%#{name}%")
    end
end
Run Code Online (Sandbox Code Playgroud)

然后:

Song.where(:working => true)
    .full_name_like('Jack Beats')
    .full_name_like('Epidemic')
    .full_name_like('Dillon Francis')
    .order('songs.published_at asc')
    .limit(1)
Run Code Online (Sandbox Code Playgroud)

如果您的应用程序要进行大量ILIKE搜索,那么您可能需要查看全文搜索系统:LIKE查询会导致表扫描,表扫描会导致悲伤.


dwu*_*urf 2

您不能在 where 子句中引用列别名。编写此查询的正确方法是:

SELECT  
  (artist_name || ' ' || name) AS full_name 
FROM "songs"  
WHERE "songs"."working" = 't' 
AND ((artist_name || ' ' || name) ILIKE('%Jack Beats%')) 
AND ((artist_name || ' ' || name) ILIKE('%Epidemic%'))
AND ((artist_name || ' ' || name) ILIKE('%Dillon Francis%'))
ORDER BY songs.published_at ASC
limit 1
;
Run Code Online (Sandbox Code Playgroud)

sub_stantial 的方法看起来更像是这样的:

select full_name 
from (
    SELECT  
        (artist_name || ' ' || name) AS full_name 
    FROM "songs"  
    WHERE "songs"."working" = 't' 
    ORDER BY songs.published_at ASC
)
WHERE (full_name ILIKE('%Jack Beats%')) 
AND (full_name ILIKE('%Epidemic%'))
AND (full_name ILIKE('%Dillon Francis%'))
LIMIT 1
;
Run Code Online (Sandbox Code Playgroud)

这两个查询的性能大致相同(相当垃圾),因为它们都必须进行全表扫描来构建 full_name 列,然后对结果进行排序。您也许可以向“working”添加索引以加快这些查询的速度。

这是postgresql 中的 sql 小提琴