2017-04-11 7 views
0

oracleデータベースに3つの表があります。彼らは、次のようになります。テーブルOrganisationにテーブルuserorganisationnameで同じ名前の列にusernameポイント:where句でlistaggによって生成された列を使用する

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 

テーブルRightは2 FOREIGN_KEYSがあります。

organisation xに適切なユーザーがいるすべてのuserについては、ユーザーが1つ以上の権利を持っているorganisations(組織xを除く)すべてのリストを取得したいと考えています。

私の例では、 には正しいユーザーが、bには正しいユーザーが、cには適切なユーザーがいません。 だから、私は、ユーザーaとb(そしてc!ではない)のすべての組織(別名!、組織名2回)を取得したいだけです。 あるユーザーが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句では使用できません。 ORA-00904:無効な識別子

私はこれをどのように達成できるか知っていますか?いいえ、私はそれを使用しようとすると、オラクルには分析関数のリストがあるので問題があると思う。 私はクエリを簡素化する方法の提案もうれしいです。ありがとう!

select * from (***long query shown above***) 
where organisations like '%termToSearch%'; 
+0

また投稿してください、あなたには現在何をしようとしていますか? –

+0

質問の最後にwhere-clauseを付けてクエリを入れます – Markus

答えて

2

ステップステップバイ::| X、その後、個別のユーザー|ユーザーのユーザー名、その後のユーザー名あたりの凝集Xを除く組織、ここで

は私がwhere句で列の組織を使用しようとしたものです。

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; 

(残念ながらLISTAGGDISTINCTキーワードを受け入れていないので、私たちは、異なる組織のリストを構築する代わりに、1の2つのステップを必要とします。)

UPDATE:あまりにも、私たちは条件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; 
+0

ありがとうThorsten。あなたのクエリは私のクエリよりもはるかに簡単に見えます(そしてwhere句で組織を使用できます)。しかし、私はあなたのクエリが私に正しい結果を与えてくれないと思います。私の例では、組織xに適切なユーザーがいて、他の組織には権利がないユーザーbがあります。私はこのユーザーを(組織を持たない)私の出力に入れたいと思っています。クエリでは、組織xにない権利のみを検索するため、このユーザーは出力されません。 – Markus

+0

あなたは正しいです。私は動作するはずのクエリを追加しました。 –

+0

ありがとう!それは今働く:) – Markus

1

変更しますコードの一部別名、

古いコードを追加している -

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%'; 

リファレンス: Schema Object Names and Qualifiers

+0

ありがとう!両方のソリューションが機能します!小文字ではなく、大文字で「組織」と書いたときに、それがなぜ機能するのか説明してください。 – Markus

+0

@Markus - Updated Answer、リファレンスリンクは、データベースオブジェクトの名前付けと保存方法について説明しています。 –

+1

@ Markus:引用符で、大文字と小文字を区別することをDBMSに指示します。引用符を付けないと、Oracleは内部的に名前を大文字で格納します。だからこそ、「組織=組織=組織=組織」<組織>ということです。 (asは途中で違いはありません) –

関連する問題