복붙노트

[SQL] 다른 주문 BY와 PostgreSQL을 DISTINCT ON

SQL

다른 주문 BY와 PostgreSQL을 DISTINCT ON

나는이 쿼리를 실행하려면 :

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

그러나 나는이 오류가 발생합니다 :

표현의 침묵 오류 BY 첫 번째 순서로 address_id을 추가,하지만 난 정말 address_id을 통해 정렬을 추가하지 않습니다. 그것은 address_id에 의해 주문없이 할 수 있습니까?

해결법

  1. ==============================

    1.문서는 말합니다 :

    문서는 말합니다 :

    공식 문서

    그래서 당신은에 의해 순서에 address_id를 추가해야합니다.

    각 address_id에 대한 가장 최근에 구입 한 제품을 포함하는 전체 행에 대해보고하는 경우 또는, 그 결과는 다음 접근 다음에 의해 해결 될 수있는 가장 큰 N 그룹별로 문제를 해결하기 위해 노력하고 purchased_at으로 분류 :

    대부분의 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
    

    @ HKF의 답변에 따라 더 PostgreSQL을 지향 솔루션 :

    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
    

    문제는 확장, 명확히 여기에 해결 : 선택 행이 다른 몇 가지 열 별개로 주문

  2. ==============================

    2.당신은 하위 쿼리에 address_id으로 주문할 수 있습니다, 당신은 외부 쿼리에서 원하는에 의해 주문한다.

    당신은 하위 쿼리에 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
    
  3. ==============================

    3.서브 쿼리는 그것을 해결할 수 :

    서브 쿼리는 그것을 해결할 수 :

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

    ORDER BY에있는 선도하는 표현은 그래서 당신은 같은 SELECT 다른 열로 위해 수 없습니다, DISTINCT ON 열 동의해야합니다.

    각 세트에서 특정 행을 선택하려는 경우에만 하위 쿼리에 의해 추가 ORDER를 사용 :

    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를 고려한다. 당신이 그것을 사용하려는 경우 그러나 있는지 확인 색인하였습니다. 보다:

    더 설명과 함께, 관련 :

  4. ==============================

    4.윈도우 함수들은 한 번에 그 해결있다 :

    윈도우 함수들은 한 번에 그 해결있다 :

    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)
    
  5. ==============================

    5.플라스크-SQLAlchemy의를 사용하는 사용자의 경우, 이것은 나를 위해 일한

    플라스크-SQLAlchemy의를 사용하는 사용자의 경우, 이것은 나를 위해 일한

    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))
    
  6. ==============================

    6.

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

    ORDER BY는 purchases.purchased_at DESC를 address_id

    address_id가 ON 대한 DISTINCT 순서로 첨가되어야한다 () 함수

  7. ==============================

    7.또한 GROUP BY 절을 사용하여이 작업을 수행 할 수 있습니다

    또한 GROUP BY 절을 사용하여이 작업을 수행 할 수 있습니다

       SELECT purchases.address_id, purchases.* FROM "purchases"
        WHERE "purchases"."product_id" = 1 GROUP BY address_id,
    purchases.purchased_at ORDER purchases.purchased_at DESC
    
  8. from https://stackoverflow.com/questions/9795660/postgresql-distinct-on-with-different-order-by by cc-by-sa and MIT license