74

Heroku を使用するために、MySQL クエリの一部を PostgreSQL に移行しています。ほとんどのクエリは正常に機能しますが、group by を使用すると同様のエラーが繰り返し発生します。

エラー: 列 "XYZ" は GROUP BY 句に指定するか、集計関数で使用する必要があります

誰かが私が間違っていることを教えてもらえますか?


100% 動作する MySQL:

SELECT `availables`.*
FROM `availables`
INNER JOIN `rooms` ON `rooms`.id = `availables`.room_id
WHERE (rooms.hotel_id = 5056 AND availables.bookdate BETWEEN '2009-11-22' AND '2009-11-24')
GROUP BY availables.bookdate
ORDER BY availables.updated_at


PostgreSQL エラー:

ActiveRecord::StatementInvalid: PGError: エラー: 列 "availables.id" は GROUP BY 句に表示されるか、集計関数で使用する必要があります:
SELECT "availables".* FROM "availables" INNER JOIN "rooms" ON "rooms". id = "availables".room_id WHERE (rooms.hotel_id = 5056 AND availables.bookdate BETWEEN E'2009-10-21' AND E'2009-10-23') GROUP BY availables.bookdate ORDER BY availables.updated_at


SQL を生成する Ruby コード:

expiration = Available.find(:all,
    :joins => [ :room ],
    :conditions => [ "rooms.hotel_id = ? AND availables.bookdate BETWEEN ? AND ?", hostel_id, date.to_s, (date+days-1).to_s ],
    :group => 'availables.bookdate',
    :order => 'availables.updated_at')  


予想される出力 (動作中の MySQL クエリから):

+-----+----------+-------+------------+---------+---- -----------+---------------+
| | ID | 価格 | スポット | 予約日 | ルームID | created_at | updated_at |
+-----+----------+-------+------------+---------+---- -----------+---------------+
| | 414 | 38.0 | 1 | 2009-11-22 | 1762年 | 2009-11-20... | 2009-11-20... |
| | 415 | 38.0 | 1 | 2009-11-23 | 1762年 | 2009-11-20... | 2009-11-20... |
| | 416 | 38.0 | 2 | 2009-11-24 | 1762年 | 2009-11-20... | 2009-11-20... |
+-----+----------+-------+------------+---------+---- -----------+---------------+
3列セット
4

9 に答える 9

114

MySQLの完全に非標準に準拠しているものGROUP BYは、PostgresによってエミュレートできますDISTINCT ON。このことを考慮:

MySQL:

SELECT a,b,c,d,e FROM table GROUP BY a

これにより、の値ごとに1行が配信されますa(これは、実際にはわかりません)。MySQLはハッシュ集計を認識していないため、実際には推測できます。おそらくソートを使用します...ただし、ソートのみを行うaため、行の順序はランダムになる可能性があります。ソートの代わりに複数列のインデックスを使用しない限り。まあ、とにかく、それはクエリによって指定されていません。

Postgres:

SELECT DISTINCT ON (a) a,b,c,d,e FROM table ORDER BY a,b,c

これにより、の値ごとに1行が配信されます。この行は、クエリで指定されaた並べ替えの最初の行になります。ORDER BY単純。

ここでは、私が計算している集計ではないことに注意してください。したがって、GROUP BY実際には意味がありません。DISTINCT ONはるかに理にかなっています。

RailsはMySQLと結婚しているので、Postgresで機能しないSQLを生成するのは驚きではありません。

于 2009-11-22T01:24:13.090 に答える
17

PostgreSQL は MySQL よりも SQL に準拠しています。出力内のすべてのフィールド (集計関数を使用した計算フィールドを除く) は、GROUP BY 句に存在する必要があります。

于 2009-11-20T09:42:32.790 に答える
11

MySQL の GROUP BY は集計関数なしで使用でき (これは SQL 標準に反します)、グループの最初の行を返します (どの基準に基づいているかわかりません) が、PostgreSQL には集計関数 (MAX、 GROUP BY 句が発行された列の SUM など)。

于 2009-11-20T09:38:10.497 に答える
5

正解です。これを修正するための解決策は、:selectを使用して、結果のオブジェクトを装飾する各フィールドを選択し、それらでグループ化することです。

厄介ですが、グループ内のフィールドを固定しない場合の意味を推測してMySQLがどのように機能するかとは対照的に、groupbyがどのように機能するかを示します

于 2009-11-20T11:29:37.140 に答える
3

私の記憶が正しければ、PostgreSQL では、GROUP BY 句が GROUP BY 句に適用されるテーブルからフェッチするすべての列を追加する必要があります

于 2009-11-20T09:38:30.563 に答える
2

最も美しい解決策ではありませんが、モデルのすべての列を出力するようにグループ パラメーターを変更すると、PostgreSQL で機能します。

expiration = Available.find(:all,
:joins => [ :room ],
:conditions => [ "rooms.hotel_id = ? AND availables.bookdate BETWEEN ? AND ?", hostel_id, date.to_s, (date+days-1).to_s ],
:group => Available.column_names.collect{|col| "availables.#{col}"},
:order => 'availables.updated_at')
于 2012-04-26T15:00:50.943 に答える
1

MySQL の "Debuking GROUP BY Myths" http://dev.mysql.com/tech-resources/articles/debunking-group-by-myths.htmlによると。SQL (標準の 2003 バージョン) では、クエリの SELECT リストで参照される列を GROUP BY 句にも含める必要はありません。

于 2011-06-02T14:38:27.487 に答える