我无法生成我确信可能的查询。我有一个products
表和一个product_changes
表。我想为每个关联产品的前30个最低值选择product_changes.rank
字段的平均值。
以下是相关的表格定义:
CREATE TABLE products (
id integer NOT NULL,
created_at timestamp without time zone
);
CREATE TABLE product_changes (
id integer NOT NULL,
product_id integer,
rank integer,
created_at timestamp without time zone
);
以下是我正在尝试的内容:
SELECT products.id, avg_rank
FROM "products"
JOIN (
SELECT product_id, AVG(rank) avg_rank
FROM product_changes
GROUP BY product_id, rank
ORDER BY rank ASC NULLS LAST
LIMIT 10) pc ON pc.product_id = products.id
WHERE avg_rank IS NOT NULL
LIMIT 10
然而,这给了我每行结果的最低30个等级值的相同平均值。这似乎ON
的{{1}}条款不起作用,但我确信这只是我对某些事情的误解。
答案 0 :(得分:1)
您的问题中有一些解释空间......
您可能希望每个产品rank
中30个最低product_changes
值的平均值。
除非您想要在product_changes
中添加没有相关行的产品,否则只需查看product_changes
- 使用子查询中的window function row_number()
即可获得快速结果:
SELECT id, avg(rank ) AS avg_rank
FROM (
SELECT product_id AS id, rank
, row_number() OVER (PARTITION BY product_id ORDER BY rank) AS rn
FROM product_changes
) sub
WHERE rn <= 30
GROUP BY id;
或许你的意思是 30个products.rank
中价值最低的产品和rank
中相关行中的平均product_changes
:
SELECT p.id, pc.avg_rank
FROM (
SELECT id
FROM products
ORDER BY rank
LIMIT 30
) p
LEFT JOIN LATERAL (
SELECT avg(rank) avg_rank
FROM product_changes
WHERE product_id = p.id
) pc ON true;
为什么LEFT JOIN LATERAL ... ON true
?
如果没有列products.rank
,您实际上是指 30个product_changes.rank
中值最低的产品:
SELECT p.id, pc.avg_rank
FROM (
SELECT product_id AS id
FROM product_changes
ORDER BY rank
LIMIT 30
) p
LEFT JOIN LATERAL (
SELECT avg(rank) avg_rank
FROM product_changes
WHERE product_id = p.id
) pc ON true;
答案 1 :(得分:0)
我会使用LATERAL
子查询或相关子查询来确保为每个产品执行子查询。这是一个例子:
SELECT products.id, avg_rank
FROM "products",
LATERAL (
SELECT AVG(rank) avg_rank
FROM (SELECT rank
FROM product_changes
WHERE product_id=products.id
ORDER BY rank ASC NULLS LAST
LIMIT 30) t1
) t2
WHERE avg_rank IS NOT NULL
LIMIT 10