Sql 将UNION重写为JOIN
我有下表:Sql 将UNION重写为JOIN,sql,postgresql,Sql,Postgresql,我有下表: CREATE TABLE temp ( grp int, version int, deleted boolean not null, PRIMARY KEY (grp, version) ); 对于每个实体grp,可以存在多个版本,版本号越大,创建版本的时间越近。由于各种原因,版本通常会被隐藏或删除。可能整个实体通常都应该隐藏,在这种情况下,grp的所有版本都将被删除 我想为每个实体选择/加入/筛选一行,其中该行要么
CREATE TABLE temp (
grp int,
version int,
deleted boolean not null,
PRIMARY KEY (grp, version)
);
对于每个实体grp,可以存在多个版本,版本号越大,创建版本的时间越近。由于各种原因,版本通常会被隐藏或删除。可能整个实体通常都应该隐藏,在这种情况下,grp的所有版本都将被删除
我想为每个实体选择/加入/筛选一行,其中该行要么是未删除的最新版本,要么是已删除该实体所有版本的最新版本
我目前有一个使用联合的解决方案,但我担心如果我尝试对联合进行进一步的连接或过滤,性能会很差,我不希望在每个联合查询中重复这些连接/过滤
下面的查询是否可以重写为不需要联合
SELECT
main.grp
, main.version
, main.deleted
-- , current_filter.version
-- , current_filter.deleted
FROM temp AS main
LEFT JOIN temp AS current_filter
ON (
current_filter.grp = main.grp
AND current_filter.version > main.version
AND NOT current_filter.deleted
)
WHERE
current_filter.version IS null
AND NOT main.deleted
UNION
SELECT
main.grp
, main.version
, main.deleted
-- , current_filter.version
-- , current_filter.deleted
-- , any_not_deleted.version
-- , any_not_deleted.deleted
FROM temp AS main
LEFT JOIN temp AS current_filter
ON (
current_filter.grp = main.grp
AND current_filter.version > main.version
)
LEFT JOIN temp AS any_not_deleted
ON (
any_not_deleted.grp = main.grp
AND any_not_deleted.version < main.version
AND NOT any_not_deleted.deleted
)
WHERE
current_filter.version IS null
AND any_not_deleted.version IS null
AND main.deleted
ORDER BY grp, version
SQLFiddle:在Postgres中,我认为最简单的解决方案是使用distinct on:
这将保持每组一行。该行是基于order by子句的第一行。使用row\u编号可以得到相同的结果:
select t.grp, t.version , t.deleted
from
(select t.grp, t.version , t.deleted
, row_number() over (partition by grp order by deleted asc , version desc) as rnum
from temp t) t
where rnum = 1
SQLFiddle:
select t.grp, t.version , t.deleted
from
(select t.grp, t.version , t.deleted
, row_number() over (partition by grp order by deleted asc , version desc) as rnum
from temp t) t
where rnum = 1