厄介なタイトルを許してください。私は質問を1つのフレーズに詰め込むのに苦労しました。誰かがより良いものを考え出すことができるなら、自由に感じてください。"many"のいくつかの基準による1対多の関連付けに基づいてクエリから結果をグループ化するにはどうすればよいですか?
私は、次の単純化されたスキーマがあります。
SELECT * FROM locations
WHERE latitude IS NOT NULL AND longitude IS NOT NULL
AND ABS(latitude - 30) + ABS(longitude - 30) < 50
ORDER BY ABS(latitude - 30) + ABS(longitude - 30) ASC
I:
vendors
INT id
locations
INT id
INT vendor_id
FLOAT latitude
FLOAT longitude
は私が復帰半径の近似によって制限距離によってソート最寄りのベンダーのリストの完全対応していますがこの瞬間、注文/制限期間の繰り返しの周りに自分の道を見つけることはできません。私は最初にSELECT
フィールドの間に "距離"としてエイリアシングを試みましたが、psqlはWHERE
節でこのエイリアスが利用できないと教えてくれました。ファイン。私の主な質問には:
私がしたいのは、それぞれが最も近い位置につながっているベンダーのリストを返すことですこのリストを近接順に並べ、半径で限定します。
私は2つのベンダーがあり、それぞれ2つのロケーションがあるとします。私は4つの場所のうちの1つだけがその場所の関連ベンダーをベンダー自身と一緒に返すように半径を制限するクエリが必要です。半径がすべての場所を網羅していれば、ベンダー1はその場所とベンダー2の間に最も近いものを提示し、そのベンダー2は最も近い場所に近接してベンダー1と2を注文することが望ましいでしょう。
MySQLでは、GROUP BY
、次にMIN(distance)
を使用して、各ベンダーの行に最も近い場所を取得できました。しかし、PostgreSQLはGROUP BY
の使用法が厳しくなっているようです。
可能であれば、SELECT
句で干渉を避けたいと思います。可能ならば上記のクエリのWHERE
とORDER
部分を再利用したいと思います。しかし、これらは決して絶対的な要件ではありません。
私はDISTINCT ON
とGROUP BY
でハックした試行をしましたが、これは私にかなりの詳細を詳しく説明しませんが、他の場所でのミラーステートメントが欠けているという点でかなり問題になりました。
ソリューション
は私がOMG Ponies' excellent answerオフベースのソリューションを採用することになりました。 OMGポニーのソリューションから
SELECT vendors.* FROM (
SELECT locations.*,
ABS(locations.latitude - 2.1) + ABS(locations.longitude - 2.1) AS distance,
ROW_NUMBER() OVER(PARTITION BY locations.locatable_id, locations.locatable_type
ORDER BY ABS(locations.latitude - 2.1) + ABS(locations.longitude - 2.1) ASC) AS rank
FROM locations
WHERE locations.latitude IS NOT NULL
AND locations.longitude IS NOT NULL
AND locations.locatable_type = 'Vendor'
) ranked_locations
INNER JOIN vendors ON vendors.id = ranked_locations.locatable_id
WHERE (ranked_locations.rank = 1)
AND (ranked_locations.distance <= 0.5)
ORDER BY ranked_locations.distance;
いくつかの偏差:
- 場所は現在、多形
_type
を経由して関連しています。少しの前提が変わります。 - サブクエリの外側で結合を移動しました。パフォーマンスの影響があるのかどうかはわかりませんが、サブクエリを場所と分割ランキングで表示し、大きなクエリをすべてまとめて表示するという意味になりました。
- minorテーブル名エイリアシングを取り除きました。私はエイリアシングに慣れていましたが、それに追随するのが難しくなりました。私はPostgreSQLを経験してからその才能を発揮するまで待つつもりです。
テーブル名の別名(主に)スタイルのポイントです:一部の人々は常にそれらを使用し、一部の人々はそれらを避けます。計算を内側のクエリに移動し、その後に追加のデータと結合して「後で」は完全にわかります。 Explain出力を見ることは、パフォーマンスに影響があるかどうかを確認する方法です。この場合、ランキング機能が暗示しているソート中にデータを保持する必要がないため、マイナーな改善が得られるかもしれません。 – araqnid