sl_*_*bug 186 sql postgresql sql-order-by distinct-on
我想运行此查询:
SELECT DISTINCT ON (address_id) purchases.address_id, purchases.*
FROM purchases
WHERE purchases.product_id = 1
ORDER BY purchases.purchased_at DESC
Run Code Online (Sandbox Code Playgroud)
但我得到这个错误:
PG ::错误:错误:SELECT DISTINCT ON表达式必须与初始ORDER BY表达式匹配
添加address_id为第一个ORDER BY表达式会使错误无效,但我真的不想添加排序address_id.是否可以不通过订购address_id?
Mos*_*cho 179
文件说:
DISTINCT ON(expression [,...])仅保留给定表达式求值的每组行的第一行.[...]请注意,每个集合的"第一行"是不可预测的,除非使用ORDER BY来确保首先出现所需的行.[...] DISTINCT ON表达式必须与最左边的ORDER 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
Run Code Online (Sandbox Code Playgroud)
一个更基于PostgreSQL的解决方案基于@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
Run Code Online (Sandbox Code Playgroud)
问题在此处得到澄清,扩展和解决:选择由某些列排序的行和在另一列上排序的行
hkf*_*hkf 54
您可以通过子查询中的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
Run Code Online (Sandbox Code Playgroud)
Erw*_*ter 40
一个子查询可以解决这个问题:
SELECT *
FROM (
SELECT DISTINCT ON (address_id) *
FROM purchases
WHERE product_id = 1
) p
ORDER BY purchased_at DESC;
Run Code Online (Sandbox Code Playgroud)
领先的表达式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;
Run Code Online (Sandbox Code Playgroud)
如果purchased_at可以NULL,请考虑DESC NULLS LAST.
相关,有更多解释:
sav*_*kov 10
窗函数可以一次解决:
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)
Run Code Online (Sandbox Code Playgroud)
对于使用Flask-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))
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
158037 次 |
| 最近记录: |