5

これをやろうとしているのはとても簡単です

 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

しかし、私は得る

ActiveRecord::StatementInvalid: PG::Error: ERROR:  column "full_name" does not exist

ステーションの前にテーブル名を追加しようとしましたが、効果はありませんでした。

4

3 に答える 3

11

コメントで sub_stantial が言及されているように、WHERE 句で SELECT からエイリアスを参照することはできません。ドワーフが提案するように派生テーブルを使用できますが、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)

この種のことを頻繁に行っている場合は、名前付きスコープが役立つ場合があります。

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

その後:

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)

アプリケーションがこのような ILIKE 検索を多数実行する場合は、全文検索システムを検討することをお勧めします。LIKE クエリはテーブル スキャンにつながり、テーブル スキャンは悲しみにつながります。

于 2012-12-03T07:50:24.570 に答える
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
;

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
;

これら 2 つのクエリのパフォーマンスはほぼ同じです (かなりゴミです)。どちらもフル テーブル スキャンを実行して full_name 列を作成し、結果を並べ替える必要があるためです。これらのクエリを高速化するために、「作業中」にインデックスを追加できる場合があります。

ここにpostgresqlのSQLフィドルがあります

于 2012-12-03T07:27:19.130 に答える