2017-06-30 8 views
1

Postgres 9.6の使用。PostgresにネストされたJSONB配列の要約統計量を効率的に計算するにはどうすればよいですか?

私はこれを有効にしていますが、より効率的な方法があると思われます。 MyEventLength配列のAVG、SUMなどを計算する最良の方法は何ですか?現在までに

DROP TABLE IF EXISTS activity; 
DROP SEQUENCE IF EXISTS activity_id_seq; 
CREATE SEQUENCE activity_id_seq; 

CREATE TABLE activity (
    id INT CHECK (id > 0) NOT NULL DEFAULT NEXTVAL ('activity_id_seq'), 
    user_id INT, 
    events JSONB 
); 

INSERT INTO activity (user_id,events) VALUES 
(1, '{"MyEvent":{"MyEventLength":[450,790,1300,5400],"MyEventValue":[334,120,120,940]}}'), 
(1, '{"MyEvent":{"MyEventLength":[12],"MyEventValue":[4]}}'), 
(2, '{"MyEvent":{"MyEventLength":[450,790,1300,5400],"MyEventValue":[334,120,120,940]}}'), 
(1, '{"MyEvent":{"MyEventLength":[1000,2000],"MyEventValue":[450,550]}}'); 

、これは私がuser_id 1のためMyEventLengthアレイの平均値を計算するために把握することができます最善の方法である:

SELECT avg(recs::text::numeric) FROM (
    SELECT jsonb_array_elements(a.event_length) as recs FROM (
     SELECT events->'MyEvent'->'MyEventLength' as event_length from activity 
     WHERE user_id = 1 
    )a 
) b; 

またはこのバリエーション:

SELECT avg(recs) FROM (
    SELECT jsonb_array_elements_text(a.event_length)::numeric as recs FROM (
     SELECT events->'MyEvent'->'MyEventLength' as event_length from activity 
     WHERE user_id = 1 
    )a 
) b; 

です多くのサブ選択を必要としないこれを行うためのよりよい方法がありますか?

答えて

1

(あなたがjsonb_array_elements_text(..)のようないくつかの集合を返す関数の出力を渡すようにするよ場合)あなたはこのようなエラーが発生しますそれ以外の場合は、avg()にスカラー値を持つ行を渡す必要があります:

ERROR: set-valued function called in context that cannot accept a set 

少なくとも1つのサブクエリまたはCTEが必要です。

オプション1、W/CTE O:

select avg(v::numeric) 
from (
    select 
    jsonb_array_elements_text(events->'MyEvent'->'MyEventLength') 
    from activity 
    where user_id = 1 
) as a(v); 

オプション2、CTE(読みやすさが優れている):

with vals as (
    select 
    jsonb_array_elements_text(events->'MyEvent'->'MyEventLength')::numeric as val 
    from activity 
    where user_id = 1 
) 
select avg(val) 
from vals 
; 

は、UPDATE、オプション3:それはあなたがそれを行うことができ、判明暗黙的にネストされたクエリを使用しないでJOIN LATERAL

select avg(val::text::numeric) 
from activity a, jsonb_array_elements(a.events->'MyEvent'->'MyEventLength') vals(val) 
where user_id = 1; 
+1

ありがとう、ありがとう! – Clay

関連する問題