2017-03-23 9 views
0

私は、クエリのGreenplumはバージョンに次のSQL Serverクエリを変換しようとしています:SQL Serverの:クロスGreenplumは(Postgresのの前LATERAL版)に参加

ことをここでの考え方があること最終テーブルには、過去30日間にアクティブな(つまり製造された)すべての部品プログラムの最新の部品が300個まで含まれています。 the answers to this questionパー

、私は、横方向が横を持っていないのPostgresの古いバージョンを使用している私の組織を除いて、それを行うだろう、JOINことを承知していますので、私が代わりに以下の機能を実現して残っていた。

CREATE FUNCTION BuildActiveParts(p_day INT, p_n INT) 
RETURNS SETOF RECORD --TABLE (part_id bigint,file_id int, measure_date timestamp, location varchar(255)) 
AS $$ 
DECLARE 
    part_active RECORD; 
    part_list RECORD; 
BEGIN 
    FOR part_active IN 
    SELECT DISTINCT qf.file_id, qf.location 
    FROM part pt 
    INNER JOIN file_model qm on qm.file_model_id = pt.file_model_id 
    INNER JOIN file qf on qf.file_id = qm.file_id WHERE pt.measure_date >= current_date - p_day LOOP 
     FOR part_list IN 
     SELECT DISTINCT pt.part_id, qf.file_id, pt.measure_date, qf.location 
     FROM part pt 
     INNER JOIN file_model qm on qm.file_model_id = pt.file_model_id 
     INNER JOIN file qf on qf.file_id = qm.file_id WHERE qf.file_id = part_active.file_id 
     AND qf.location = part_active.location 
     ORDER BY pt.measure_date DESC LIMIT p_n LOOP 
      RETURN NEXT part_list; 
     END LOOP; 
    END LOOP; 
END 
$$ LANGUAGE plpgsql; 

-- Later used in: 

--Build list of all active programs in last p_day days. This temporary table is a component of a larger function that produces a table based on this and other other calculations, called daily. 
-- Note: this insert yields 'function cannot execute because it accesses relation' 
    INSERT INTO TMP_part_list (part_id, file_id, measure_date, location) 
    SELECT DISTINCT * FROM BuildActiveParts(p_day, p_n) AS active_parts (part_id int, file_id text, measure_date timestamp, location text) 
    ; 

残念ながら、この関数は別のテーブルへの挿入(私のビジネス要件の避けられない現実)で使用されるので、関数が孤立して実行されたときにうれしい幸せな結果を返しますが、その目的に使用しようとすると大きな怒りを感じます目的。私は「代わりにVIEWを作成する」という効果についての提案を見てきましたが、この機能のスクリプトから生じるビューが一部であるため、実際にはオプションではありません。

赤ちゃんのジャングルから数か月にわたる遠足で、私の組織に自分のものを更新してこれを解決するように説得することはできますか?

編集:ここではコメントに基づいて、いくつかの試みは、次のとおりですのでfunction cannot execute on segment because it accesses relationの仕事しませんでした機能を持つ

試み、:機能なし

DROP FUNCTION IF EXISTS BuildRecentParts(TEXT, TEXT, INT); 

CREATE FUNCTION BuildRecentParts(file_id TEXT, location_in TEXT, p_n INT) 
RETURNS SETOF RECORD --TABLE (measure_date timestamp, part_id bigint) 
AS $$ 
DECLARE 
    part_list RECORD; 
BEGIN 
     FOR part_list IN 
     SELECT DISTINCT pt.measure_date, pt.part_id 
     FROM part pt 
     INNER JOIN file_model qm on qm.file_model_id = pt.file_model_id 
     INNER JOIN file qf on qf.file_id = qm.file_id 
     WHERE qf.file_id = file_id 
     AND qf.edl_desc = location_in 
     ORDER BY pt.measure_date DESC LIMIT p_n LOOP 
      RETURN NEXT part_list; 
    END LOOP; 
END 
$$ LANGUAGE plpgsql; 

SELECT DISTINCT qf.file_id, qf.edl_desc, (SELECT pti.measure_date, pti.part_id FROM part pti 
     INNER JOIN file_model qmi on qmi.file_model_id = pti.file_model_id 
     INNER JOIN file qfi on qfi.file_id = qmi.file_id 
     WHERE qfi.file_id = qf.file_id 
     AND qfi.edl_desc = qf.edl_desc 
     ORDER BY pti.measure_date DESC LIMIT 300) 
FROM part pt 
     INNER JOIN file_model qm on qm.file_model_id = pt.file_model_id 
     INNER JOIN file qf on qf.file_id = qm.file_id 
WHERE pt.measure_date >= current_date - 30 ; 

試みサブクエリが複数の列を持っているため、動作しません。

CREATE TEMPORARY TABLE TMP_TMP1 (part_id bigint, file_id varchar(255), location varchar(255), measure_date timestamp) DISTRIBUTED BY (part_id); 

INSERT INTO TMP_TMP1 (part_id, file_id, location, measure_date) 
    SELECT DISTINCT pt.part_id, qf.file_id, qf.edl_desc, pt.measure_date 
    FROM part pt 
    INNER JOIN file_model qm on qm.file_model_id = pt.file_model_id 
    INNER JOIN file qf on qf.file_id = qm.file_id; 
ANALYZE TMP_TMP1; 


SELECT DISTINCT t1.file_id, t1.location, (SELECT t2.measure_date, t2.part_id FROM TMP_TMP1 t2 
     WHERE t2.file_id = t1.file_id 
     AND t2.location = t1.location 
     ORDER BY t2.measure_date DESC LIMIT 300) 
FROM TMP_TMP1 t1 
WHERE t1.measure_date >= current_date - 30; 

私も再帰的なCTEを試みましたが、それはサポートされていませんでした。

+1

リンクされた質問の回答には、古いバージョンでLATERALをエミュレートする方法の良い例が含まれています。あなたはそれらを試しましたか? (すなわち、サブSELECT /関数呼び出しを 'SELECT'節a.k.a.の相関サブクエリに入れてください) – pozs

+0

私は「関係にアクセスするので実行できません」と言ってくれました。私はチャンスを得るときに試して編集します。 –

+0

これは、(LATERAL以外の)もう一つの緑色の制限かもしれません:http://stackoverflow.com/questions/21615211/function-cannot-execute-on-segment-because-it-accesses-relation- * Greenplumの関数は次のとおりです。 Postgresに比べて制限されています。関数が "リレーション"(thinkテーブル)にアクセスする場合、別のテーブルの選択でそれを呼び出すことはできません。* - 関数を使用せずに相関サブクエリを試してみてください。 – pozs

答えて

0

Greenplumにはダーティリードがないので、あなたは持っているノーロックヒントを実装できません。それはおそらく良いことかもしれません。私もSQL Serverから削除することをお勧めします。

私は最良の解決策は、その機能の代わりにここで分析機能を使用すること、またはGreenplumがサポートする相関サブクエリを使用することだと思います。また、このアプローチを使用する方がSQL Serverのほうが効率的です。あなたの元のグループがこれをすることによって含まれているため、複数のqf.qcc_file_desc値を持っている場合は、あなたの元のクエリとのトラブルに得ることができるようにそれが見えるので

SELECT sub2.part_id, sub2.location, sub2.measure_date 
FROM (
    SELECT sub1.part_id, sub1.location, sub1.measure_date, row_number() over(partition by sub1.part_id order by sub1.measure_date desc) as rownum 
    FROM (
     SELECT pt.part_id, qf.edl_desc as location, pt.measure_date 
     FROM part pt 
     INNER JOIN file_model qm on qm.file_model_id = pt.file_model_id 
     INNER JOIN file qf on qf.file_id = qm.file_id 
     WHERE pt.measure_date >= (now() - interval '30 days') 
     GROUP BY pt.part_id, qf.edl_desc, pt.measure_date 
     ) AS sub1 
    ) as sub2 
WHERE sub2.rownum <= 300; 

さて、私はあなたのデータを推測しなければなりませんでした。複数の価値を持っていれば、物事は醜くなるでしょう。

データを知らなくても、row_number関数で100%確実ではありません。ここでは、私の組織の建築家からの回答の間

row_number() over(partition by sub1.part_id, sub1.location order by sub1.measure_date desc) 
+0

申し訳ありませんが、あなたの評価に影響する名前を修正しながら、私は一箇所を逃しました。また、過去30日以内に製造された部品に限定されているコンポーネントはありません。 –

+0

私はSQLを編集します。 –

0

は、私たちが克服するにはあまりにもコストがかかるGreenplumは制限を打っていると判断し、クロス結合を実行ロジックがシフトされます。それは代わりに、このかもしれませんこの機能が含まれているはずのストアドプロシージャを呼び出すRスクリプトに渡します。

関連する問題