为什么我的横向连接中的 LIMIT 被忽略了?
Why is the LIMIT in my lateral join being ignored?
我有一个 table 像这样:
create table cars (
id serial primary key,
au_rating integer,
year integer
);
insert into cars (au_rating, year) VALUES
(1,2019),
(1,2020),
(1,2016),
(2,2016),
(2,2019),
(3,2020),
(3,2018),
(3,2017),
(3,2019),
(3,2020),
(0,2020),
(0,2006)
;
我想 select 每个组中的第 N 个元素使用 JOIN LATERAL
(类似于此:):
SELECT cars_outer.id, cars_top.au_rating, cars_top.year
FROM cars cars_outer
JOIN LATERAL (
SELECT * FROM cars cars_inner
WHERE cars_inner.au_rating = cars_outer.au_rating
ORDER BY ABS(cars_inner.year - 2019)
LIMIT 2
) cars_top on true
ORDER BY cars_outer.au_rating DESC
然而,由于我只希望在每组 au_rating 中最多有 2 行,我为横向连接提供了一个 LIMIT 2
,但它似乎被忽略了 - 为什么?
如果您想要每个评分组的前 2 条记录,那么我建议使用 window 函数进行过滤。
你似乎想要的逻辑是:
select (c.c).*
from (
select c, row_number() over(partition by au_rating order by year) rn
from cars c
) c
where rn <= 2
我不确定您如何定义“前 2 名”记录。这按年份对记录进行排序,因此每个 au_rating
得到两个 oldest 记录。您可以将 order by
子句更改为您的实际需求。
id | au_rating | year
-: | --------: | ---:
12 | 0 | 2006
11 | 0 | 2020
3 | 1 | 2016
1 | 1 | 2019
4 | 2 | 2016
5 | 2 | 2019
8 | 3 | 2017
7 | 3 | 2018
GMB 对您接受的 window 函数的回答是最好的。
LIMIT
在您的 LATERAL JOIN
查询中得到了尊重。问题是记录重复,而您省略了 DISTINCT
.
更新
我没有提到您想要 cars_top.id
而不是 cars_outer.id
,并且 DISTINCT 意味着 order_by
列必须在结果中。
SELECT DISTINCT cars_top.id, cars_top.au_rating, cars_top.year
FROM cars cars_outer
JOIN LATERAL (
SELECT * FROM cars cars_inner
WHERE cars_inner.au_rating = cars_outer.au_rating
ORDER BY ABS(cars_inner.year - 2019)
LIMIT 2
) cars_top on true
ORDER BY cars_top.au_rating DESC
您的查询完全您所请求的。对于您 table 中的每辆车,它会返回匹配的汽车。
您可以通过让第一个“table”仅标识您想要的评级来做您想做的事:
SELECT cars_top.au_rating, cars_top.year
FROM (SELECT DISTINCT au_rating FROM cars
) cars_outer CROSS JOIN LATERAL
(SELECT *
FROM cars cars_inner
WHERE cars_inner.au_rating = cars_outer.au_rating
ORDER BY ABS(cars_inner.year - 2019)
LIMIT 2
) cars_top
ORDER BY cars_outer.au_rating DESC;
请注意,如果您使用 CROSS JOIN LATERAL
,则不需要 ON
子句。
我有一个 table 像这样:
create table cars (
id serial primary key,
au_rating integer,
year integer
);
insert into cars (au_rating, year) VALUES
(1,2019),
(1,2020),
(1,2016),
(2,2016),
(2,2019),
(3,2020),
(3,2018),
(3,2017),
(3,2019),
(3,2020),
(0,2020),
(0,2006)
;
我想 select 每个组中的第 N 个元素使用 JOIN LATERAL
(类似于此:):
SELECT cars_outer.id, cars_top.au_rating, cars_top.year
FROM cars cars_outer
JOIN LATERAL (
SELECT * FROM cars cars_inner
WHERE cars_inner.au_rating = cars_outer.au_rating
ORDER BY ABS(cars_inner.year - 2019)
LIMIT 2
) cars_top on true
ORDER BY cars_outer.au_rating DESC
然而,由于我只希望在每组 au_rating 中最多有 2 行,我为横向连接提供了一个 LIMIT 2
,但它似乎被忽略了 - 为什么?
如果您想要每个评分组的前 2 条记录,那么我建议使用 window 函数进行过滤。
你似乎想要的逻辑是:
select (c.c).*
from (
select c, row_number() over(partition by au_rating order by year) rn
from cars c
) c
where rn <= 2
我不确定您如何定义“前 2 名”记录。这按年份对记录进行排序,因此每个 au_rating
得到两个 oldest 记录。您可以将 order by
子句更改为您的实际需求。
id | au_rating | year -: | --------: | ---: 12 | 0 | 2006 11 | 0 | 2020 3 | 1 | 2016 1 | 1 | 2019 4 | 2 | 2016 5 | 2 | 2019 8 | 3 | 2017 7 | 3 | 2018
GMB 对您接受的 window 函数的回答是最好的。
LIMIT
在您的 LATERAL JOIN
查询中得到了尊重。问题是记录重复,而您省略了 DISTINCT
.
更新
我没有提到您想要 cars_top.id
而不是 cars_outer.id
,并且 DISTINCT 意味着 order_by
列必须在结果中。
SELECT DISTINCT cars_top.id, cars_top.au_rating, cars_top.year
FROM cars cars_outer
JOIN LATERAL (
SELECT * FROM cars cars_inner
WHERE cars_inner.au_rating = cars_outer.au_rating
ORDER BY ABS(cars_inner.year - 2019)
LIMIT 2
) cars_top on true
ORDER BY cars_top.au_rating DESC
您的查询完全您所请求的。对于您 table 中的每辆车,它会返回匹配的汽车。
您可以通过让第一个“table”仅标识您想要的评级来做您想做的事:
SELECT cars_top.au_rating, cars_top.year
FROM (SELECT DISTINCT au_rating FROM cars
) cars_outer CROSS JOIN LATERAL
(SELECT *
FROM cars cars_inner
WHERE cars_inner.au_rating = cars_outer.au_rating
ORDER BY ABS(cars_inner.year - 2019)
LIMIT 2
) cars_top
ORDER BY cars_outer.au_rating DESC;
请注意,如果您使用 CROSS JOIN LATERAL
,则不需要 ON
子句。