programing

순서가 다른 PostgreSQL DISTING ON입니다.

newsource 2023. 4. 25. 22:28

순서가 다른 PostgreSQL DISTING ON입니다.

다음 쿼리를 실행합니다.

SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC

하지만 다음과 같은 오류가 발생합니다.

PG::오류:ERROR: SELECT DISTING ON 식은 초기 ORDER BY 식과 일치해야 합니다.

추가하고 있습니다.address_id처음처럼요ORDER BY표현은 오류를 잠재우지만, 정렬을 추가하고 싶지 않습니다.address_id. 다음 날짜까지 주문하지 않고 할 수 있습니까?address_id?

문서에는 다음과 같이 나와 있습니다.

DISTINT ON(식 [, ...])은 지정된 식이 동일한 것으로 평가되는 각 행 집합의 첫 번째 행만 유지합니다. [...] 각 세트의 "첫 번째 행"은 원하는 행이 먼저 나타나도록 하기 위해 사용되지 않는 한 예측할 수 없습니다. [...식별 ORTINT ON 식은 왼쪽 MOST BY 식과 일치해야 합니다.

공식 문서입니다.

따라서 다음을 추가해야 합니다.address_id명령대로 하겠습니다.

또는 각 항목에 대해 가장 최근에 구입한 제품이 들어 있는 전체 열을 찾는 경우입니다.address_id그리고 그 결과는 다음과 같이 정렬됩니다.purchased_at그룹당 가장 큰 N개의 문제를 해결하려고 합니다. 이 문제는 다음과 같은 방법으로 해결할 수 있습니다.

대부분의 DBMS에서 작동해야 하는 일반적인 솔루션은 다음과 같습니다.

SELECT t1.* FROM purchases t1
JOIN (
    SELECT address_id, max(purchased_at) max_purchased_at
    FROM purchases
    WHERE product_id = 1
    GROUP BY address_id
) t2
ON t1.address_id = t2.address_id AND t1.purchased_at = t2.max_purchased_at
ORDER BY t1.purchased_at DESC

더 많은 포스트그레입니다.SQL 지향 솔루션은 @hkf의 답변을 기반으로 합니다.

SELECT * FROM (
  SELECT DISTINCT ON (address_id) *
  FROM purchases 
  WHERE product_id = 1
  ORDER BY address_id, purchased_at DESC
) t
ORDER BY purchased_at DESC

여기서 문제를 명확히 하고, 확장하고, 해결합니다. 일부 열에 따라 정렬된 행과 다른 열에 따라 구별되는 행을 선택합니다.

하위 쿼리를 통해 해결할 수 있습니다.

SELECT *
FROM  (
    SELECT DISTINCT ON (address_id) *
    FROM   purchases
    WHERE  product_id = 1
    ) p
ORDER  BY purchased_at DESC;

선행 표현식입니다.ORDER BY의 컬럼과 일치해야 합니다.DISTINCT ON, 따라서 동일한 열에서 서로 다른 열을 기준으로 정렬할 수 없습니다.SELECT.

추가 항목만 사용하십시오.ORDER BY각 세트에서 특정 행을 선택하려면 하위 쿼리에서 다음을 수행합니다.

SELECT *
FROM  (
    SELECT DISTINCT ON (address_id) *
    FROM   purchases
    WHERE  product_id = 1
    ORDER  BY address_id, purchased_at DESC  -- get "latest" row per address_id
    ) p
ORDER  BY purchased_at DESC;

한다면purchased_at수 있습니다.NULL,사용하다DESC NULLS LAST- 최상의 성능을 위해 지수를 일치시킵니다.다음을 참조하십시오.

관련, 자세한 설명과 함께 다음과 같습니다.

하위 쿼리에서 address_id별로 정렬한 다음 외부 쿼리에서 원하는 대로 정렬할 수 있습니다.

SELECT * FROM 
    (SELECT DISTINCT ON (address_id) purchases.address_id, purchases.* 
    FROM "purchases" 
    WHERE "purchases"."product_id" = 1 ORDER BY address_id DESC ) 
ORDER BY purchased_at DESC

윈도우 기능은 이 문제를 한 번에 해결할 수 있습니다.

SELECT DISTINCT ON (address_id) 
   LAST_VALUE(purchases.address_id) OVER wnd AS address_id
FROM "purchases"
WHERE "purchases"."product_id" = 1
WINDOW wnd AS (
   PARTITION BY address_id ORDER BY purchases.purchased_at DESC
   ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)

Flask-SQ 사용하시는 분들을 위한 것입니다.LALchemy, 이건 나한테 효과가 있었어요.

from app import db
from app.models import Purchases
from sqlalchemy.orm import aliased
from sqlalchemy import desc

stmt = Purchases.query.distinct(Purchases.address_id).subquery('purchases')
alias = aliased(Purchases, stmt)
distinct = db.session.query(alias)
distinct.order_by(desc(alias.purchased_at))

또한 다른 답변과 함께 다음 쿼리를 사용하여 해결할 수 있습니다.

WITH purchase_data AS (
        SELECT address_id, purchased_at, product_id,
                row_number() OVER (PARTITION BY address_id ORDER BY purchased_at DESC) AS row_number
        FROM purchases
        WHERE product_id = 1)
SELECT address_id, purchased_at, product_id
FROM purchase_data where row_number = 1

그룹별 절을 사용하여 이 작업을 수행할 수도 있습니다.

   SELECT purchases.address_id, purchases.* FROM "purchases"
    WHERE "purchases"."product_id" = 1 GROUP BY address_id,
purchases.purchased_at ORDER purchases.purchased_at DESC

언급URL : https://stackoverflow.com/questions/9795660/postgresql-distinct-on-with-different-order-by 입니다.