2017-02-09 5 views
2

問題は以下の通りである:PostgreSQLの前と次のグループ値

と仮定、私は(それは私が働いているテーブルのサブサンプルされ)、そのようなビューのテーブルを持っている:

| col1 | col2 | 
|------|------| 
| 1 | a2 | 
| 1 | b2 | 
| 2 | c2 | 
| 2 | d2 | 
| 2 | e2 | 
| 1 | f2 | 
| 1 | g2 | 
| 3 | h2 | 
| 1 | j2 | 

私は2つの新しい列現在

  • に等しいないcol1の前の値を含む

    • prevを追加する必要があります以前の値が存在しない場合が現在

    からcol1内の次の値が等しくない含有する、prevには次の値が存在しない場合、現在のcol1の値ならびにnext電流値を含まなければならない含まなければなりません。私は任意のヘルプ感謝するでしょう

    | col1 | col2 | prev | next | 
    |------|------|------|------| 
    | 1 | a2 | 1 | 2 | 
    | 1 | b2 | 1 | 2 | 
    | 2 | c2 | 1 | 1 | 
    | 2 | d2 | 1 | 1 | 
    | 2 | e2 | 1 | 1 | 
    | 1 | f2 | 2 | 3 | 
    | 1 | g2 | 2 | 3 | 
    | 3 | h2 | 1 | 1 | 
    | 1 | j2 | 3 | 1 | 
    

    結果は次の形式を持つ必要があります。

  • +1

    ウィンドウ関数 –

    +0

    https://www.postgresql.org/docs/current/static/tutorial-window.html –

    +1

    SQLテーブルは、*順序付けられていない*セットを表します。列に順序が指定されていない限り、「前」または「次の」値はありません。データの列は、データを注文する際の明白な列のようには見えません。 –

    答えて

    1

    あなたはウィンドウ関数leadlagfirst_valuelast_valuesumのこの使用して組み合わせを試すことができます。

    select 
        t.col1, t.col2, n, 
        coalesce(first_value(y) over (partition by x order by col2), col1) prev_val, 
        coalesce(last_value(y2) over (partition by x order by col2 
         rows between current row and unbounded following), col1) next_val 
    from (
        select 
         t.*, 
         case when col1 <> lag(col1) over (order by col2) then lag(col1) over (order by col2) end y, 
         case when col1 <> lead(col1) over (order by col2) then lead(col1) over (order by col2) end y2, 
         sum(n) over (order by col2) x 
        from (
         select 
          t.*, 
          case when col1 <> lag(col1) over (order by col2) then 1 else 0 end n 
         from t 
        ) t 
    ) t; 
    

    行のグループごとに進み/遅れを検出します。

    1

    注文を指定するid列があると仮定すると、これも可能です。私はこれがウィンドウ関数を使って簡単に表現されているかどうかは分かりません。

    あなたは、相関サブクエリを使用することができます。

    select t.*, 
         (select t2.col1 
         from t t2 
         where t2.id < t.id and t2.col1 <> t.col1 
         order by t2.id desc 
         fetch first 1 row only 
         ) as prev_col1, 
         (select t2.col1 
         from t t2 
         where t2.id > t.id and t2.col1 <> t.col1 
         order by t2.id asc 
         fetch first 1 row only 
         ) as prev_col2 
    from t; 
    

    あなたが以前と次の値を欠落しているためcoalece()を追加することができます。それは問題の興味深い部分ではありません。

    0
    WITH cte AS (
    SELECT row_number() over() rowid, * 
        FROM unnest(array[1,1,2,2,2,1,1,3,1], array['a2','b2','c2','d2','e2','f2','g2','h2','j2']) t(col1,col2) 
    ) 
    SELECT t.col1, 
         t.col2, 
         COALESCE(prev.col1,t.col1) prev, 
         COALESCE("next".col1,t.col1) "next" 
        FROM cte t 
        LEFT JOIN LATERAL (SELECT prev.col1 
             FROM cte prev 
             WHERE prev.rowid < t.rowid 
              AND prev.col1 != t.col1 
             ORDER BY prev.rowid DESC 
             LIMIT 1 
            ) prev ON True 
        LEFT JOIN LATERAL (SELECT "next".col1 
             FROM cte "next" 
             WHERE "next".rowid > t.rowid 
              AND "next".col1 != t.col1 
             ORDER BY "next".rowid ASC 
             LIMIT 1 
            ) "next" ON True 
    
    関連する問題