Techioz Blog

PG::エラー: SELECT DISTINCT、ORDER BY 式は選択リストに含める必要があります

概要

イベント Web サイトを作成しており、レンダリングされた RSVPS をイベントの開始時間で並べ替えようとしています。 RSVPS がたくさんあるので、個別にグループ化していますが、ここ数日間、PG でこのエラーが表示されずに結果を並べ替えるのに非常に苦労していました。このトピックに関する以前の質問をいくつか見ましたが、まだかなり迷っています。どうすればこれを機能させることができますか?どうもありがとうございます!

@rsvps = Rsvp.where(:voter_id => current_user.following.collect {|f| f["id"]}, :status => 'going').where("start_time > ? AND start_time < ?", Time.now, Time.now + 1.month).order("count_all desc").count(:group => :event_id).collect { |f| f[0] }

<%= render :partial => 'rsvps/rsvp', :collection => Rsvp.where(:event_id => @rsvps).select("DISTINCT(event_id)").order('start_time asc') %>

解決策

これはかなり古い質問であることは承知していますが、Postgres に SELECT DISTINCT / ORDER BY 列に対してこの一見奇妙な制限がある理由を理解するのに役立つ小さな例を頭の中で検討しました。

Rsvp テーブルに次のデータがあると想像してください。

 event_id |        start_time
----------+------------------------
    0     | Mar 17, 2013  12:00:00
    1     |  Jan 1, 1970  00:00:00
    1     | Aug 21, 2013  16:30:00
    2     |  Jun 9, 2012  08:45:00

ここで、それぞれの start_time 順に並べられた個別のevent_id のリストを取得したいとします。しかし、1はどこに行けばよいでしょうか? 1 つのタプルは 1970 年 1 月 1 日に始まるため、それを最初に置くべきでしょうか、それとも 2013 年 8 月 21 日を理由に最後に置くべきでしょうか?

データベース システムはその決定を行うことができず、クエリの構文は操作対象となる実際のデータに依存できないため (event_id が一意であると仮定して)、並べ替えは SELECT 句の列によるもののみに制限されます。 。

実際の質問に関しては、マシューの答えに代わる方法は、並べ替えに MIN や MAX などの集計関数を使用することです。

  SELECT event_id
    FROM Rsvp
GROUP BY event_id
ORDER BY MIN(start_time)

start_time での明示的なグループ化と集計により、データベースは結果タプルの明確な順序付けを行うことができます。ただし、この場合、読みやすさが間違いなく問題になることに注意してください ;)