어색한 제목을 용서하십시오. 나는 내 질문을 한 문구로 증오하는 데 어려움을 겪었다. 누구든지 더 나은 것을 생각해 낼 수 있다면, 자유롭게 느끼십시오."many"의 일부 기준에 따라 일대 다 연관을 기반으로하는 쿼리의 결과를 그룹화하는 방법은 무엇입니까?
나는 다음과 같은 단순화 된 스키마가 :
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
절에서 사용할 수 없다고 말했습니다. 벌금. 이 주위에 멋진 바지 방법이 있다면, 나는 모든 귀에 있지만 내 주요 질문에 대한 :
내가 뭘하고 싶은지, 각각의 가장 가까운 위치와 함께 조인 업체 목록을 반환하는 것입니다 이 목록을 근접으로 정렬하고 반지름으로 제한하십시오.
두 개의 공급 업체가 있다고 가정하면 각각은 두 곳입니다. 반경을 제한하는 쿼리를 사용하여 네 위치 중 하나만이 그 위치의 관련 공급 업체를 공급 업체 자체와 함께 반환하도록합니다. 반경이 모든 위치를 포함한다면, 나는 벤더 1이 가장 가까운 위치에, 벤더 2가 가장 가까운 위치에, 결국 벤더 1과 2를 가까운 위치의 근접을 기준으로 정렬하기를 원할 것이다.
MySQL에서 나는 GROUP BY
을 사용하여 각 공급 업체 행에서 가장 가까운 위치를 얻은 다음 MIN(distance)
을 사용했습니다. 그러나 PostgreSQL은 GROUP BY
의 사용에있어보다 엄격한 것으로 보입니다.
가능하면 SELECT
절에 간섭하는 것을 피하고 싶습니다. 가능한 경우 위 질문에 WHERE
및 ORDER
부분을 다시 사용하고 싶습니다. 그러나 이것들은 절대로 절대적인 요구 사항은 아닙니다.
나는 DISTINCT ON
과 GROUP BY
에 hackneyed 시도를했다. 그러나 이것들은 내가 다른 곳에서 미러링 된 문장을 놓치고 있다는 점에서 상당한 문제를 일으켰다. 지금은 자세하게 설명하지 않을 것이다.
솔루션
나는 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