2016-03-22 7 views
1

PostgreSQL 8.2.15(Greenplum Database 4.3.3.1 build 1)を使用しています。つまり、WITH RECURSIVEの使用はサポートされていません。SQLクエリ:深さ3度までの接続先の検索

サンプル・テーブルがあります:SQLを介して

select * from reports_Table 

reporter spammer 
AAA BBB 
AAA CCC 
DDD CCC 
DDD BBB 
DDD EEE 
DDD FFF 
EEE DDD 
CCC AAA 
FFF DDD 
BBB AAA 
BBB CCC 
BBB DDD 

、私は深さの三親等まで、AAAに接続されているすべての記者のリストだけでなく、スパマーを取得しようとしています。上記の例では、クエリからの結果は次のようになります

AAA 
BBB 
CCC 
DDD 
FFF 
EEE 

BBB及びCCCはAAA AAAの、従って1度接続、それはCCCを介して接続されているので
DDDは、AAAの2度接続であると直接接続されています。 、
FFFとEEEは、両方ともDDDで接続されているため、AAAの3次接続です。

私は論理的にそれがうまくいくと思うクエリで、この時点で取得するために管理しているが、発生した構文エラーを理解するように見えることはできませんので、先に進むことはできません。

ERROR: syntax error at or near "WHILE" 

おそらく私が使用しているバージョンは、WHILE LOOPの構文が異なる必要がありますが、修正できないようです。

/*supported tables*/ 
CREATE TEMP TABLE variables as 
select 1 as first_column, 'AAA'::text as specific_reporter, 3 as degreeNumber 

CREATE TEMP TABLE CollectedReporters(
specific_reporter text 
); 
GO 
INSERT INTO CollectedReporters 
select specific_reporter from variables; 

/*main query*/ 
BEGIN 
    WHILE (select degreeNumber from variables) >= 1 LOOP 
     INSERT INTO CollectedReporters 
      SELECT ct.spammer::text as specific_reporter 
       FROM reports_Table ct 
        INNER JOIN CollectedReporters cc ON ct.reporter = cc.specific_reporter::text 
        LEFT JOIN CollectedReporters cc2 ON ct.spammer = cc2.specific_reporter::text 
       WHERE cc2.specific_reporter IS NULL; 

     UPDATE variables 
      SET degreeNumber = degreeNumber - 1; 
    END WHILE; 
END; 

SELECT * FROM CollectedReporters 

ご協力いただきありがとうございます。

+0

問題を理解するのに役立つエラーが含まれています。 – 0x0FFF

+1

サンプルデータでは、「bbb」が「1度」で、「fff」が「3度」であることがどのようになっていますか?私はサンプルデータからその結論にどのように到達しているのか分かりません。 – JNevill

+0

私はあなたがPostgresで再帰クエリ 'WITH RECURSIVE'を使ってこれを効率的に行うことができると思います。 http://www.postgresql.org/docs/8.4/static/queries-with.html –

答えて

1

問題ここでは、データベースの構文を理解していないことを、私はthe guide on PGをカバーするためにあなたをお勧めしたいです、それはあなたのために物事がより明確になるだろう

  • まず、あなたは、BEGIN-ENDの構文を使用することができますPL/pgSQL言語構文の一部であるため、PL/pgSQLの内部でのみ機能します。関数の外で使用すると、 "BEGIN"はトランザクションの開始を意味し、適切に使用する必要があります。
  • GUIツールでクエリを実行する場合、各クエリは正しいANSI SQLクエリでなければなりません。 "while"はANSI SQLの一部ではありません。ただし、MSSQLのT-SQL、OracleのPL/SQL、PostgresのPL/pgSQLの一部です。
  • Greenplumバージョン4.3以前でPL/pgSQLを使用するには、関数を作成するオプションが1つしかありません。 Greenplumはバージョン5.0以上では(DEVはgithubのからビルド)、あなたはまた、ここではPL/pgSQLの

を匿名コードブロックを使用することができ、このように見えるかもしれない方法の一例である:私はあなたがすべきだと思う

CREATE OR REPLACE FUNCTION my_function (maxlevel int) returns void as $BODY$ 
DECLARE 
    level int = 1; 
BEGIN 

    TRUNCATE CollectedReporters; 

    WHILE (level <= maxlevel) LOOP 
     RAISE NOTICE 'Processing level %', level; 

     INSERT INTO CollectedReporters 
      SELECT ct.spammer::text as specific_reporter 
       FROM reports_Table ct 
        INNER JOIN CollectedReporters cc ON ct.reporter = cc.specific_reporter::text 
        LEFT JOIN CollectedReporters cc2 ON ct.spammer = cc2.specific_reporter::text 
       WHERE cc2.specific_reporter IS NULL; 

     level = level + 1; 
    END LOOP; 
END; 
$BODY$ LANGUAGE PLPGSQL VOLATILE; 
+0

これは非常に役に立ちました、ありがとうございました! –

関連する問題