在 where 子句中使用 listagg 生成的列
Using column generated by listagg in a where clause
我在 oracle 数据库中有 3 个 table。它们看起来像这样:
Table User:
username|forename|surname
a a a
b b b
c c c
Table Right:
username|organisationname|right
a x user
a x admin
a x owner
a y user
a y admin
a z owner
b x user
c y user
c y admin
c z user
Table Organisation:
organisationname|number
x 12
y 14
z 42
tableRight
有两个foreign_keys:username
指向tableuser
中同名的列organisationname
到 table Organisation
.
对于在 organisation
x 上拥有正确用户的所有 user
,我想获取所有 organisations
(组织 x 除外)的列表,其中用户拥有 1 个或多个权利。
在我的例子中:
a 在 x 上有正确的用户,b 在 x 上有正确的用户,c 在 x 上没有正确的用户。
所以我只想为用户 a 和 b(而不是 c!!!)获取所有组织(不同!,两次没有组织名称)。
如果一个用户对另一个组织没有权限而不是 x(他必须有正确的用户),我希望输出中有该用户但没有组织。
预期输出为:
user|organisations
a y; z
b
希望你明白我的意思。
到目前为止,我的查询如下:
select username,
/* listagg put all the organisationnames of one user in one column separated by ;
then the organsation x gets removed from the result*/
regexp_replace (listagg (organisationname, '; ')
within group (order by organisationname), '(^x;?)|( ?x;)|(; x$) ', '') as "organisations"
from(
select u2.username as username,
o.organisationname as organisationname,
/*I do this to remove duplicate entries in the list of organisations of one user */
row_number() over (partition by u2.username, o.organisationname order by u2.username) as rn
from RIGHT r2, ORGANISATION o, USER u2
where r2.organisationname = o.organisationname
and r2.username = u2.username
and r2.username IN
(
select u.username
from USER u, right r
where r.username = u.username
and r.right = 'user'
)
order by u2.username, o.organisationname
)
where rn = 1
group by username
该查询有效,但现在我想过滤列组织。但我无法在 where 子句中使用它。当我尝试使用它时,oracle 抛出错误:
ORA-00904: 标识符无效
有谁知道我怎样才能做到这一点?我觉得oracle有问题是因为解析函数listagg。
对于如何简化我的查询的建议,我也很高兴。谢谢!
以下是我尝试在 where 子句中使用列组织的方法:
select * from ( ***long query shown above***)
where organisations like '%termToSearch%';
逐步:用户的用户名|x,然后是除 x 之外的不同用户|组织,然后是每个用户名的聚合:
select
username,
listagg(organisationname, '; ') within group (order by organisationname) as organisations
from
(
select distinct username, organisationname
from right
where username in
(
select username
from right
where organisationname = 'x' and right = 'user'
)
and organisationname <> 'x'
)
group by username;
(遗憾的是 LISTAGG
不接受 DISTINCT
关键字,因此我们需要两个步骤而不是一个步骤来构建不同组织的列表。)
更新: 为了让用户也没有任何其他组织,我们将删除条件 and organisationname <> 'x'
并向 LISTAGG
添加一个案例结构:
select
username,
listagg(case when organisationname <> 'x' then organisationname end, '; ')
within group (order by organisationname) as organisations
from
(
select distinct username, organisationname
from right
where username in
(
select username
from right
where organisationname = 'x' and right = 'user'
)
)
group by username;
更改要添加别名的代码部分,
旧代码 -
within group (order by organisationname), '(^x;?)|( ?x;)|(; x$) ', '') as "organisations"
新代码 -
within group (order by organisationname), '(^x;?)|( ?x;)|(; x$) ', '') organisations
或
新代码 -
within group (order by organizationname), '(^x;?)|( ?x;)|(; x$) ', '') as "ORGANISATIONS"
如果您仍想使用旧代码,可以将最后一个 where 条件更改为 -
where "organisations" like '%termToSearch%';
我在 oracle 数据库中有 3 个 table。它们看起来像这样:
Table User:
username|forename|surname
a a a
b b b
c c c
Table Right:
username|organisationname|right
a x user
a x admin
a x owner
a y user
a y admin
a z owner
b x user
c y user
c y admin
c z user
Table Organisation:
organisationname|number
x 12
y 14
z 42
tableRight
有两个foreign_keys:username
指向tableuser
中同名的列organisationname
到 table Organisation
.
对于在 organisation
x 上拥有正确用户的所有 user
,我想获取所有 organisations
(组织 x 除外)的列表,其中用户拥有 1 个或多个权利。
在我的例子中: a 在 x 上有正确的用户,b 在 x 上有正确的用户,c 在 x 上没有正确的用户。 所以我只想为用户 a 和 b(而不是 c!!!)获取所有组织(不同!,两次没有组织名称)。 如果一个用户对另一个组织没有权限而不是 x(他必须有正确的用户),我希望输出中有该用户但没有组织。
预期输出为:
user|organisations
a y; z
b
希望你明白我的意思。 到目前为止,我的查询如下:
select username,
/* listagg put all the organisationnames of one user in one column separated by ;
then the organsation x gets removed from the result*/
regexp_replace (listagg (organisationname, '; ')
within group (order by organisationname), '(^x;?)|( ?x;)|(; x$) ', '') as "organisations"
from(
select u2.username as username,
o.organisationname as organisationname,
/*I do this to remove duplicate entries in the list of organisations of one user */
row_number() over (partition by u2.username, o.organisationname order by u2.username) as rn
from RIGHT r2, ORGANISATION o, USER u2
where r2.organisationname = o.organisationname
and r2.username = u2.username
and r2.username IN
(
select u.username
from USER u, right r
where r.username = u.username
and r.right = 'user'
)
order by u2.username, o.organisationname
)
where rn = 1
group by username
该查询有效,但现在我想过滤列组织。但我无法在 where 子句中使用它。当我尝试使用它时,oracle 抛出错误: ORA-00904: 标识符无效
有谁知道我怎样才能做到这一点?我觉得oracle有问题是因为解析函数listagg。 对于如何简化我的查询的建议,我也很高兴。谢谢!
以下是我尝试在 where 子句中使用列组织的方法:
select * from ( ***long query shown above***)
where organisations like '%termToSearch%';
逐步:用户的用户名|x,然后是除 x 之外的不同用户|组织,然后是每个用户名的聚合:
select
username,
listagg(organisationname, '; ') within group (order by organisationname) as organisations
from
(
select distinct username, organisationname
from right
where username in
(
select username
from right
where organisationname = 'x' and right = 'user'
)
and organisationname <> 'x'
)
group by username;
(遗憾的是 LISTAGG
不接受 DISTINCT
关键字,因此我们需要两个步骤而不是一个步骤来构建不同组织的列表。)
更新: 为了让用户也没有任何其他组织,我们将删除条件 and organisationname <> 'x'
并向 LISTAGG
添加一个案例结构:
select
username,
listagg(case when organisationname <> 'x' then organisationname end, '; ')
within group (order by organisationname) as organisations
from
(
select distinct username, organisationname
from right
where username in
(
select username
from right
where organisationname = 'x' and right = 'user'
)
)
group by username;
更改要添加别名的代码部分,
旧代码 -
within group (order by organisationname), '(^x;?)|( ?x;)|(; x$) ', '') as "organisations"
新代码 -
within group (order by organisationname), '(^x;?)|( ?x;)|(; x$) ', '') organisations
或
新代码 -
within group (order by organizationname), '(^x;?)|( ?x;)|(; x$) ', '') as "ORGANISATIONS"
如果您仍想使用旧代码,可以将最后一个 where 条件更改为 -
where "organisations" like '%termToSearch%';