2017-05-18 15 views
0

は、私はこのようなテーブルがあります。Oracle SQLで一意のタグをグループ化する方法は?

GROUPID | TAG 
------ | ------ 
1  | Tag1 Tag2 
1  | Tag1 Tag3 
1  | Tag1 Tag4 
2  | Tag5 Tag6 
2  | Tag4 Tag3 

をそして、私は次の結果を取得したい:オラクルSQLで重複タグをフィルタリングする方法

GROUP | TAG 
------- | ------- 
1  | Tag1 Tag2 Tag3 Tag4 
2  | Tag3 Tag4 Tag5 Tag6 

やアイデアを?コメントで述べたようmathguy

おかげ

+2

悪い考えがすべてです。 「私が持っている」とは何ですか?入力データ(最初のテーブル)はディスク上のストアド・テーブルですか? 「結果」とは何を意味しますか?報告目的のために表示されるものは何ですか?その場合、おそらくその形式でレポートを取得することはOKですが、基本データはリレーショナルテーブル設計の最も基本的な原則の1つに違反します。基本的には、実際には「最初の標準形」と呼ばれています。そのような場合の最善の解決策は、データを正規化することです。データベースにアクセスできない場合は、少なくとも照会することができます。 – mathguy

+0

Jackには、1行あたりGroupIdごとに2つのタグ、または1行に任意の数のタグが常に付いていますか? – alexgibbs

+0

行ごとに任意のタグになります。そしてそれは空にもなる可能性があります。ありがとう。 -Jack – user3595231

答えて

1

、このようなクエリは、設計の変更により簡素化することができます。
ただし、この形式のデータを使用すると、につき、TAGのユニークなセットを引き出すことができます。ここに例のアプローチがあります:

この最初の段階では、を使用して、各行に含まれるTAGの数を確認します。次に、は、各行にそれぞれTAG位置タグ番号を生成します。最後に、各行の各複合語TAGの所定の位置にタグを抽出します。

まず、テストテーブルを作成:(GROUPIDあたりが、より多くの行)ONLY_ONE_TAG

WITH COUNTED_TAG AS (
    SELECT GROUPID, "TAG", REGEXP_COUNT("TAG",'(^|)[^ ]{1,}') AS TAG_COUNT FROM GROUPID_TAG), 
    KEYED_COUNTED_TAG AS (
    SELECT GROUPID, "TAG", TAG_COUNT, TAG_KEG_GENERATOR.TAG_KEY FROM COUNTED_TAG 
     INNER JOIN (SELECT LEVEL AS TAG_KEY FROM DUAL CONNECT BY LEVEL <= 999) TAG_KEG_GENERATOR 
     ON TAG_KEG_GENERATOR.TAG_KEY <= COUNTED_TAG.TAG_COUNT) 
SELECT DISTINCT GROUPID, REPLACE(REGEXP_SUBSTR("TAG",'(^|)[^ ]{1,}',1,TAG_KEY),' ','') AS ONLY_ONE_TAG 
FROM KEYED_COUNTED_TAG 
ORDER BY 1 ASC, 2 ASC; 

に以下のクエリは2つの列を生成します

CREATE TABLE GROUPID_TAG(
    GROUPID NUMBER, 
    "TAG" VARCHAR2(256) 
); 

INSERT INTO GROUPID_TAG VALUES (1,'Tag1 Tag2'); 
INSERT INTO GROUPID_TAG VALUES (1,'Tag1 Tag3'); 
INSERT INTO GROUPID_TAG VALUES (1,'Tag1 Tag4'); 
INSERT INTO GROUPID_TAG VALUES (2,'Tag5 Tag6'); 
INSERT INTO GROUPID_TAG VALUES (2,'Tag4 Tag3'); 

、単一TAGでは、それを実行します与える:

GROUPID ONLY_ONE_TAG 
1  Tag1   
1  Tag2   
1  Tag3   
1  Tag4   
2  Tag3   
2  Tag4   
2  Tag5   
2  Tag6  

この時点でのデータは、元の状態よりも扱いやすい場合があります。しかし、GROUPIDごとに1つの行に再集計したい場合は、その例を示します。私たちの最後のクエリから始めて、私たちは物事を集約するLISTAGGを追加します:

WITH COUNTED_TAG AS (
    SELECT GROUPID, "TAG", REGEXP_COUNT("TAG",'(^|)[^ ]{1,}') AS TAG_COUNT FROM GROUPID_TAG), 
    KEYED_COUNTED_TAG AS (
    SELECT GROUPID, "TAG", TAG_COUNT, TAG_KEG_GENERATOR.TAG_KEY FROM COUNTED_TAG 
     INNER JOIN (SELECT LEVEL AS TAG_KEY FROM DUAL CONNECT BY LEVEL <= 999) TAG_KEG_GENERATOR 
     ON TAG_KEG_GENERATOR.TAG_KEY <= COUNTED_TAG.TAG_COUNT), 
    DISTINCT_TAG AS(SELECT DISTINCT GROUPID, REPLACE(REGEXP_SUBSTR("TAG",'(^|)[^ ]{1,}',1,TAG_KEY),' ','') AS ONLY_ONE_TAG 
        FROM KEYED_COUNTED_TAG) 
SELECT GROUPID, LISTAGG(ONLY_ONE_TAG,' ') WITHIN GROUP (ORDER BY ONLY_ONE_TAG ASC) AS AGGREGATED_TAG 
FROM DISTINCT_TAG 
GROUP BY GROUPID 
ORDER BY 1 ASC; 

結果:

GROUPID AGGREGATED_TAG  
1  Tag1 Tag2 Tag3 Tag4 
2  Tag3 Tag4 Tag5 Tag6 

を次に、テストのために、いくつかの追加のタグを追加:

INSERT INTO GROUPID_TAG VALUES (1,'Wookie Hobbit @[email protected]'); 
INSERT INTO GROUPID_TAG VALUES (2,'HAL-9000 Thor'); 

をと再度クエリ:

WITH COUNTED_TAG AS (
    SELECT GROUPID, "TAG", REGEXP_COUNT("TAG",'(^|)[^ ]{1,}') AS TAG_COUNT FROM GROUPID_TAG), 
    KEYED_COUNTED_TAG AS (
    SELECT GROUPID, "TAG", TAG_COUNT, TAG_KEG_GENERATOR.TAG_KEY FROM COUNTED_TAG 
     INNER JOIN (SELECT LEVEL AS TAG_KEY FROM DUAL CONNECT BY LEVEL <= 999) TAG_KEG_GENERATOR 
     ON TAG_KEG_GENERATOR.TAG_KEY <= COUNTED_TAG.TAG_COUNT), 
    DISTINCT_TAG AS(SELECT DISTINCT GROUPID, REPLACE(REGEXP_SUBSTR("TAG",'(^|)[^ ]{1,}',1,TAG_KEY),' ','') AS ONLY_ONE_TAG 
        FROM KEYED_COUNTED_TAG) 
SELECT GROUPID, LISTAGG(ONLY_ONE_TAG,' ') WITHIN GROUP (ORDER BY ONLY_ONE_TAG ASC) AS AGGREGATED_TAG 
FROM DISTINCT_TAG 
GROUP BY GROUPID 
ORDER BY 1 ASC; 

結果:

GROUPID AGGREGATED_TAG       
1  @[email protected] Hobbit Tag1 Tag2 Tag3 Tag4 Wookie 
2  HAL-9000 Tag3 Tag4 Tag5 Tag6 Thor  
+0

ありがとうございます。しかし、どういうわけか、このSQLは – user3595231

+0

ありがとう@ user3595231あなたのコメントが切れたようです。このsqlが実行されないことを意味しましたか?使用しているOracleのバージョンは何ですか?あなたは例外を含めることができますか?ありがとう – alexgibbs

+0

GROUPID_TAG TABLEのTAGに2つ以上のタグが含まれている場合、私はいくつかの奇妙な結果を見ます。これは私が "INSERT INTO GROUPID_TAG VALUES(2、 'AAA BBB CCC DDD'); COMMIT"を追加したもので、そのSQLを実行すると、結果は "2"グループのタグの一部にしかなりませんでした。 - ジャック。 – user3595231

関連する問題