如何使用 DISTINCT ON 但 ORDER BY 另一个表达式?

How to use DISTINCT ON but ORDER BY another expression?

模特Subscriptionhas_manySubscriptionCart.

A SubscriptionCart 有一个 status 和一个 authorized_at 日期。

我需要从与 Subscription 关联的所有购物车中选择日期最旧的 authorized_at 购物车,然后我必须通过此命令对所有返回的 Subscription 结果进行排序subscription_carts.authorized_at 列。

下面的查询有效,但我不知道如何 select DISTINCT ON subscription.id 避免重复但 ORDER BY subscription_carts.authorized_at .

到目前为止的原始 sql 查询:

select distinct on (s.id) s.id as subscription_id, subscription_carts.authorized_at, s.*
from subscriptions s
join subscription_carts subscription_carts on subscription_carts.subscription_id = s.id 
and subscription_carts.plan_id = s.plan_id
where subscription_carts.status = 'processed'
and s.status IN ('authorized','in_trial', 'paused')
order by s.id, subscription_carts.authorized_at

如果我首先尝试 ORDER BY subscription_carts.authorized_at,我会得到一个错误,因为 DISTINCT ONORDER BY 表达式必须按相同的顺序。

我找到的解决方案似乎对我的需要来说太复杂了,但我未能实施它们,因为我不完全理解它们。

GROUP BY subscription_id 然后从该组中选择而不是使用 DISTINCT ON 会更好吗?任何帮助表示赞赏。

此要求是使 DISTINCT ON 工作所必需的;要更改最终顺序,您可以添加一个带有另一个 ORDER BY 子句的外部查询:

SELECT *
FROM (SELECT DISTINCT ON (s.id)
             s.id as subscription_id, subscription_carts.authorized_at, s.*
      FROM subscriptions s
         JOIN ...
      WHERE ...
      ORDER BY s.id, subscription_carts.authorized_at
     ) AS subq
ORDER BY authorized_at;

您不必使用 DISTINCT ON。虽然它偶尔有用,但我个人发现 window 基于函数的方法更加清晰:

-- Optionally, list all columns explicitly, to remove the rn column again
SELECT *
FROM (
  SELECT
    s.id AS subscription_id,
    c.authorized_at,
    s.*,
    ROW_NUMBER () OVER (PARTITION BY s.id ORDER BY c.authorized_at) rn
  FROM subscriptions s
  JOIN subscription_carts c
  ON c.subscription_id = s.id
  AND c.plan_id = s.plan_id
  WHERE c.status = 'processed'
  AND s.status IN ('authorized', 'in_trial', 'paused')
) t
WHERE rn = 1
ORDER BY subscription_id, authorized_at