39

関連 -異なる ORDER BY を使用した PostgreSQL DISTINCT ON

テーブル購入があります (product_id、 purchase_at、address_id)

サンプルデータ:

| id | product_id |   purchased_at    | address_id |
| 1  |     2      | 20 Mar 2012 21:01 |     1      |
| 2  |     2      | 20 Mar 2012 21:33 |     1      |
| 3  |     2      | 20 Mar 2012 21:39 |     2      |
| 4  |     2      | 20 Mar 2012 21:48 |     2      |

私が期待する結果は、各 address_id の最新の購入製品 (完全な行) であり、その結果は purchase_at フィールドによって子孫順に並べ替える必要があります。

| id | product_id |   purchased_at    | address_id |
| 4  |     2      | 20 Mar 2012 21:48 |     2      |
| 2  |     2      | 20 Mar 2012 21:33 |     1      |

クエリの使用:

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

私は得ています:

| id | product_id |   purchased_at    | address_id |
| 2  |     2      | 20 Mar 2012 21:33 |     1      |
| 4  |     2      | 20 Mar 2012 21:48 |     2      |

したがって、行は同じですが、順序が間違っています。それを修正する方法はありますか?

4

3 に答える 3

26

かなり明確な質問:)

SELECT t1.* FROM purchases t1
LEFT JOIN purchases t2
ON t1.address_id = t2.address_id AND t1.purchased_at < t2.purchased_at
WHERE t2.purchased_at IS NULL
ORDER BY t1.purchased_at DESC

そしておそらくより速いアプローチ:

SELECT t1.* FROM purchases t1
JOIN (
    SELECT address_id, max(purchased_at) max_purchased_at
    FROM purchases
    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
于 2012-03-20T22:45:08.967 に答える
13

ORDER BY は、個別の address_id ごとに生成する行を選択するためにDISTINCT ONによって使用されます。結果のレコードを並べ替える場合は、DISTINCT ON を副選択にして、その結果を並べ替えます。

SELECT * FROM
(
  SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
  FROM "purchases"
  WHERE "purchases"."product_id" = 2
  ORDER BY purchases.address_id ASC, purchases.purchased_at DESC
) distinct_addrs
order by distinct_addrs.purchased_at DESC
于 2012-03-21T04:18:01.187 に答える