Oracle KEEP DENSE_RANK FIRST 的 Postgres 转换
Postgres Conversion of ORacle KEEP DENSE_RANK FIRST
将特定系统从 Oracle 转换为 Postgres,我在其中使用 Oracle KEEP dense rank first 函数。在那个系统中(出于各种原因)更新语句必须像这样格式化:
UPDATE aaa a
SET a.dataval =
(SELECT MAX (b.data_val) KEEP (DENSE_RANK FIRST ORDER BY b.sort_val)
FROM bbb b
WHERE a.id = b.aaa_id);
或者为了测试,我们可以将其编写为 Oracle 的内联视图样式:
SELECT id,
(SELECT MAX (b.data_val) KEEP (DENSE_RANK FIRST ORDER BY b.sort_val)
FROM bbb b
WHERE a.id = b.aaa_id)
FROM aaa a;
所以我在 Postgres 中尝试了类似的构造,以及许多其他尝试 window 和行范围等
select id,
(select first_value(b.data_val) over (order by b.sort_val)
from bbb b
where a.id = b.aaa_id )
from aaa a;
我得到了错误:
SQL Error [21000]: ERROR: more than one row returned by a subquery used as an expression.
我原以为 aaa 的每一行都会 return 来自 bbb table 的一行。但这似乎并没有发生。有没有办法以这种方式为 Postgres 格式化查询?非常感谢 Postrges 新手的任何帮助。
这是在 Oracle 中创建测试对象的脚本。
CREATE TABLE aaa (
id integer NOT NULL,
dataval integer NULL
);
CREATE TABLE bbb (
aaa_id integer NOT NULL,
bbb_id integer NOT NULL,
sort_val integer NOT NULL,
data_val integer NOT NULL
);
INSERT INTO aaa (id,dataval) VALUES (1,NULL);
INSERT INTO aaa (id,dataval) VALUES (2,NULL);
INSERT INTO aaa (id,dataval) VALUES (3,NULL);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (1,1,3,10);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (1,2,2,11);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (1,3,1,12);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (2,4,6,13);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (2,5,5,14);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (2,6,4,15);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (3,7,9,16);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (3,8,8,17);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (3,9,7,18);
--Query
SELECT id,
(SELECT MAX (b.data_val) KEEP (DENSE_RANK FIRST ORDER BY b.sort_val)
FROM bbb b
WHERE a.id = b.aaa_id)
FROM aaa a;
/*expected Result
ID DATAVAL
1 12
2 15
3 18
*/
这是 Postgres 的相同测试对象设置:
CREATE TABLE aaa (
id int8 NOT NULL,
dataval int8 NULL
);
CREATE UNIQUE INDEX aaa_id_idx ON aaa (id);
CREATE TABLE bbb (
aaa_id int8 NOT NULL,
bbb_id int8 NOT NULL,
sort_val int8 NOT NULL,
data_val int8 NOT NULL
);
CREATE UNIQUE INDEX bbb_aaa_id_idx ON bbb on (aaa_id, bbb_id);
INSERT INTO aaa (id,dataval) VALUES
(1,NULL),
(2,NULL),
(3,NULL);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES
(1,1,3,10),
(1,2,2,11),
(1,3,1,12),
(2,4,6,13),
(2,5,5,14),
(2,6,4,15),
(3,7,9,16),
(3,8,8,17),
(3,9,7,18);
谢谢!
您可以使用带有行限制子句的子查询或横向连接
select a.id, b.data_val
from aaa a
left join lateral (
select b.data_val
from bbb b
where b.aaa_id = a.id
order by b.sort_val
limit 1
) b on true
另一个选择是 distinct on
:
select distinct on (a.id) a.id, b.data_val
from aaa a
left join bbb b on b.aaa_id = a.id
order by a.id, b.sort_val
Demo on DB Fiddle - 两个查询都产生:
id | data_val
-: | -------:
1 | 12
2 | 15
3 | 18
如果你想要更新:
update aaa a
set data_val = (
select b.data_val
from bbb b
where b.aaa_id = a.id
order by sort_val
limit 1
)
将特定系统从 Oracle 转换为 Postgres,我在其中使用 Oracle KEEP dense rank first 函数。在那个系统中(出于各种原因)更新语句必须像这样格式化:
UPDATE aaa a
SET a.dataval =
(SELECT MAX (b.data_val) KEEP (DENSE_RANK FIRST ORDER BY b.sort_val)
FROM bbb b
WHERE a.id = b.aaa_id);
或者为了测试,我们可以将其编写为 Oracle 的内联视图样式:
SELECT id,
(SELECT MAX (b.data_val) KEEP (DENSE_RANK FIRST ORDER BY b.sort_val)
FROM bbb b
WHERE a.id = b.aaa_id)
FROM aaa a;
所以我在 Postgres 中尝试了类似的构造,以及许多其他尝试 window 和行范围等
select id,
(select first_value(b.data_val) over (order by b.sort_val)
from bbb b
where a.id = b.aaa_id )
from aaa a;
我得到了错误:
SQL Error [21000]: ERROR: more than one row returned by a subquery used as an expression.
我原以为 aaa 的每一行都会 return 来自 bbb table 的一行。但这似乎并没有发生。有没有办法以这种方式为 Postgres 格式化查询?非常感谢 Postrges 新手的任何帮助。
这是在 Oracle 中创建测试对象的脚本。
CREATE TABLE aaa (
id integer NOT NULL,
dataval integer NULL
);
CREATE TABLE bbb (
aaa_id integer NOT NULL,
bbb_id integer NOT NULL,
sort_val integer NOT NULL,
data_val integer NOT NULL
);
INSERT INTO aaa (id,dataval) VALUES (1,NULL);
INSERT INTO aaa (id,dataval) VALUES (2,NULL);
INSERT INTO aaa (id,dataval) VALUES (3,NULL);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (1,1,3,10);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (1,2,2,11);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (1,3,1,12);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (2,4,6,13);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (2,5,5,14);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (2,6,4,15);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (3,7,9,16);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (3,8,8,17);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES (3,9,7,18);
--Query
SELECT id,
(SELECT MAX (b.data_val) KEEP (DENSE_RANK FIRST ORDER BY b.sort_val)
FROM bbb b
WHERE a.id = b.aaa_id)
FROM aaa a;
/*expected Result
ID DATAVAL
1 12
2 15
3 18
*/
这是 Postgres 的相同测试对象设置:
CREATE TABLE aaa (
id int8 NOT NULL,
dataval int8 NULL
);
CREATE UNIQUE INDEX aaa_id_idx ON aaa (id);
CREATE TABLE bbb (
aaa_id int8 NOT NULL,
bbb_id int8 NOT NULL,
sort_val int8 NOT NULL,
data_val int8 NOT NULL
);
CREATE UNIQUE INDEX bbb_aaa_id_idx ON bbb on (aaa_id, bbb_id);
INSERT INTO aaa (id,dataval) VALUES
(1,NULL),
(2,NULL),
(3,NULL);
INSERT INTO bbb (aaa_id,bbb_id,sort_val,data_val) VALUES
(1,1,3,10),
(1,2,2,11),
(1,3,1,12),
(2,4,6,13),
(2,5,5,14),
(2,6,4,15),
(3,7,9,16),
(3,8,8,17),
(3,9,7,18);
谢谢!
您可以使用带有行限制子句的子查询或横向连接
select a.id, b.data_val
from aaa a
left join lateral (
select b.data_val
from bbb b
where b.aaa_id = a.id
order by b.sort_val
limit 1
) b on true
另一个选择是 distinct on
:
select distinct on (a.id) a.id, b.data_val
from aaa a
left join bbb b on b.aaa_id = a.id
order by a.id, b.sort_val
Demo on DB Fiddle - 两个查询都产生:
id | data_val -: | -------: 1 | 12 2 | 15 3 | 18
如果你想要更新:
update aaa a
set data_val = (
select b.data_val
from bbb b
where b.aaa_id = a.id
order by sort_val
limit 1
)