Postgres - 动态生成多行和多列并加入现有的 table
Postgres - generate multiple rows and columns dynamically and join to an existing table
我正在尝试将 oracle 查询转换为 postgres。
Oracle 查询使用以下生成动态 table 类数据:
SELECT ROWNUM TYPE_ID, regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) TYPE
FROM DUAL
CONNECT BY regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) IS NOT NULL
Output:
TYPE_ID,TYPE
1,NED
2,SED
3,ZED
4,MED
考虑样本 table:
create table details(
Title Varchar,
Misc Varchar
);
insert into details values ('DBA','5 years');
这是整个查询:
select /*ACC DATA*/ (case when ACC.TYPE_ID= 4 then null else
Title end) Job_title,
ACC.* from DUAL,
(SELECT ROWNUM TYPE_ID, regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) TYPE
FROM DUAL
CONNECT BY regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) IS NOT NULL) ACC,
details
Output looks like this:
JOB_TITLE,TYPE_ID,TYPE
DBA,1,NED
DBA,2,SED
DBA,3,ZED
如此有效,查询将详细信息 table 的每一行返回三次,其中 TYPE_ID 分别为 1、2、3,TYPE 分别为 NED、SED、ZED。
如何在 Postgres 11.5 中实现这一点?
如您所见,Postres 没有有用的 "connect by ..."。但它确实有其他同样有用的功能。在这种情况下:(参见 fiddle)
- regexp_split_to_table()
- string_to_array() 和 unnest
两者都会将字符串解析为单个元素。不幸的是,它们都没有提供枚举,但是,它很容易从窗口函数 row_number 中获得。因此,您的 Oracle 语句变为(type 是 Postgres 中的保留字,会产生错误,因此我更改为 type_val。)
select row_number() over() type_id,type_val
from (select unnest(string_to_array('NED,SED,ZED,MED',',')) type_val ) sl
有了它,只需一个简单的步骤就可以将它与您的详细信息进行交叉连接 table 得到您想要的。
with split_list(type_id,type_val) as
( select row_number() over() type_id,type_val
from (select unnest(string_to_array('NED,SED,ZED,MED',',')) type_val ) sl
)
select title, type_id, type_val
from details
cross join split_list
where type_id != 4;
我正在尝试将 oracle 查询转换为 postgres。
Oracle 查询使用以下生成动态 table 类数据:
SELECT ROWNUM TYPE_ID, regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) TYPE
FROM DUAL
CONNECT BY regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) IS NOT NULL
Output:
TYPE_ID,TYPE
1,NED
2,SED
3,ZED
4,MED
考虑样本 table:
create table details(
Title Varchar,
Misc Varchar
);
insert into details values ('DBA','5 years');
这是整个查询:
select /*ACC DATA*/ (case when ACC.TYPE_ID= 4 then null else
Title end) Job_title,
ACC.* from DUAL,
(SELECT ROWNUM TYPE_ID, regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) TYPE
FROM DUAL
CONNECT BY regexp_substr('NED,SED,ZED,MED', '[^,]+', 1, LEVEL) IS NOT NULL) ACC,
details
Output looks like this:
JOB_TITLE,TYPE_ID,TYPE
DBA,1,NED
DBA,2,SED
DBA,3,ZED
如此有效,查询将详细信息 table 的每一行返回三次,其中 TYPE_ID 分别为 1、2、3,TYPE 分别为 NED、SED、ZED。
如何在 Postgres 11.5 中实现这一点?
如您所见,Postres 没有有用的 "connect by ..."。但它确实有其他同样有用的功能。在这种情况下:(参见 fiddle)
- regexp_split_to_table()
- string_to_array() 和 unnest
两者都会将字符串解析为单个元素。不幸的是,它们都没有提供枚举,但是,它很容易从窗口函数 row_number 中获得。因此,您的 Oracle 语句变为(type 是 Postgres 中的保留字,会产生错误,因此我更改为 type_val。)
select row_number() over() type_id,type_val
from (select unnest(string_to_array('NED,SED,ZED,MED',',')) type_val ) sl
有了它,只需一个简单的步骤就可以将它与您的详细信息进行交叉连接 table 得到您想要的。
with split_list(type_id,type_val) as
( select row_number() over() type_id,type_val
from (select unnest(string_to_array('NED,SED,ZED,MED',',')) type_val ) sl
)
select title, type_id, type_val
from details
cross join split_list
where type_id != 4;