복붙노트

[SQL] 윈도우 기능 : LAST_VALUE (BY ... ASC ORDER) LAST_VALUE과 동일 (ORDER BY ... DESC)

SQL

윈도우 기능 : LAST_VALUE (BY ... ASC ORDER) LAST_VALUE과 동일 (ORDER BY ... DESC)

샘플 데이터

CREATE TABLE test
    (id integer, session_ID integer, value integer)
;

INSERT INTO test
    (id, session_ID, value)
VALUES
    (0, 2, 100),
    (1, 2, 120),
    (2, 2, 140),
    (3, 1, 900),
    (4, 1, 800),
    (5, 1, 500)
;

현재 쿼리

select 
id,
last_value(value) over (partition by session_ID order by id) as last_value_window,
last_value(value) over (partition by session_ID order by id desc) as last_value_window_desc
from test
ORDER BY id

나는 LAST_VALUE () 윈도우 기능에 문제로 실행되었다 : http://sqlfiddle.com/#!15/bcec0/2

바이올린에서 나는 LAST_VALUE () 쿼리 내에서 정렬 방향으로 해결하려고 노력하고있다.

편집하다: 문제는되지 않습니다 : 나는 모든 시간 마지막 값 방법과 프레임 절을 사용하는 방법 (무제한의 이전 및 억제 할 다음)를하지 않는 이유는. 나는 FIRST_VALUE (내림차순) 및 LAST_VALUE () 및 LAST_VALUE ()는 당신에게 모든 시간 마지막 값을 제공하지 않는 문제의 차이에 대해 알고 :

기본 프레임 절은 현재 행까지 위의 제한은 없습니다. 그래서 첫 번째 값은 항상 절을 withing에 첫 번째 행을주고있다. 단지 하나의 행이있는 경우는 문제가되지 않습니다 그래서 또는 1 hundered가 (프레임 절은 모두 백 포함) (프레임 절은이 하나를 포함). 결과는 항상 첫 번째입니다. DESC 순서는 동일합니다 : DESC 정렬 순서를 변경 한 후 첫 번째 행은 마지막 값, 당신은 얼마나 많은 행이없는 문제입니다.

LAST_VALUE으로 () 동작은 매우 유사하다 :이 한 행 : 당신은 하나 개의 행이있는 경우, 그것은 당신에게 기본 프레임 조항의 마지막 값을 제공합니다. 두번째 행에서, 프레임 절 마지막 번째이며, 두 개의 행을 포함한다. () LAST_VALUE는 현재 행까지 모든 행의 마지막 행을하지만 마지막 행을 포기하지 않는 이유입니다.

내가 DESC I에 순서를 변경하지만 내가 첫 번째 행에서이 하나를 얻을 수 있도록 내가 두 번째 행 등에서 마지막으로 두 번째보다, 우선 마지막 행을 가지고 기대하고있다. 하지만 그 결과가 아니다. 왜?

현재 예를 들어이는 FIRST_VALUE (), FIRST_VALUE (내림차순)) (LAST_VALUE, LAST_VALUE (내림차순)과 내가이 LAST_VALUE (내림차순)에 대한 기대 오전에 대한 결과는 다음과 같습니다

 id | fv_asc | fv_desc | lv_asc | lv_desc | lv_desc(expecting)
----+--------+---------+--------+---------+--------------------
  0 |    100 |     140 |    100 |     100 |    140
  1 |    100 |     140 |    120 |     120 |    120
  2 |    100 |     140 |    140 |     140 |    100
  3 |    900 |     500 |    900 |     900 |    500
  4 |    900 |     500 |    800 |     800 |    800
  5 |    900 |     500 |    500 |     500 |    900

나에게는 DESC 플래그 BY 순서는 기본 프레임 절 LAST_VALUE () 호출 내에서 무시됩니다 것으로 보인다. 하지만 그것은 FIRST_VALUE () 호출 내에 있지 않습니다. 내 질문은 그래서 왜이 LAST_VALUE이다 ()는 LAST_VALUE (내림차순)과 같은 결과?

해결법

  1. ==============================

    1.LAST_VALUE ()의 문제는 절을 윈도의 기본 규칙은 당신이 정말로 원하는 값을 제거하는 것입니다. 이것은 매우 미묘한 문제이며이 기능을 지원하는 모든 데이터베이스의 사실이다.

    LAST_VALUE ()의 문제는 절을 윈도의 기본 규칙은 당신이 정말로 원하는 값을 제거하는 것입니다. 이것은 매우 미묘한 문제이며이 기능을 지원하는 모든 데이터베이스의 사실이다.

    이것은 오라클 블로그에서 온다 :

    따라서, 단지 FIRST_VALUE ()를 사용합니다. 이것은 당신이 원하는 것을 :

    with test (id, session_ID, value) as (
          (VALUES (0, 2, 100),
                  (1, 2, 120),
                  (2, 2, 140),
                  (3, 1, 900),
                  (4, 1, 800),
                  (5, 1, 500)
          )
         )
    select id,
           first_value(value) over (partition by session_ID order by id) as first_value_window,
           first_value(value) over (partition by session_ID order by id desc) as first_value_window_desc
    from test
    order by id
    
  2. ==============================

    2.1 년 후에 나는 해결책을 가지고있다 :

    1 년 후에 나는 해결책을 가지고있다 :

    이 문장을 가지고 :

    SELECT
        id,
        array_accum(value) over (partition BY session_ID ORDER BY id)      AS window_asc,
        first_value(value) over (partition BY session_ID ORDER BY id)      AS first_value_window_asc,
        last_value(value) over (partition BY session_ID ORDER BY id)       AS last_value_window_asc,
        array_accum(value) over (partition BY session_ID ORDER BY id DESC) AS window_desc,
        first_value(value) over (partition BY session_ID ORDER BY id DESC) AS first_value_window_desc,
        last_value(value) over (partition BY session_ID ORDER BY id DESC)  AS last_value_window_desc
    FROM
        test
    ORDER BY
        id
    

    이것은 제공

    id  window_asc     first_value_window_asc  last_value_window_asc  window_desc    first_value_window_desc  last_value_window_desc  
    --  -------------  ----------------------  ---------------------  -------------  -----------------------  ----------------------  
    0   {100}          100                     100                    {140,120,100}  140                      100                     
    1   {100,120}      100                     120                    {140,120}      140                      120                     
    2   {100,120,140}  100                     140                    {140}          140                      140                     
    3   {900}          900                     900                    {500,800,900}  500                      900                     
    4   {900,800}      900                     800                    {500,800}      500                      800                     
    5   {900,800,500}  900                     500                    {500}          500                      500           
    

    array_accum는 사용 된 창을 보여줍니다. 첫 번째와 윈도우의 현재 마지막 값을가 볼 수 있습니다.

    쇼에게 실행 계획을 무슨 일이 있었는지 :

    "Sort  (cost=444.23..449.08 rows=1940 width=12)"
    "  Sort Key: id"
    "  ->  WindowAgg  (cost=289.78..338.28 rows=1940 width=12)"
    "        ->  Sort  (cost=289.78..294.63 rows=1940 width=12)"
    "              Sort Key: session_id, id"
    "              ->  WindowAgg  (cost=135.34..183.84 rows=1940 width=12)"
    "                    ->  Sort  (cost=135.34..140.19 rows=1940 width=12)"
    "                          Sort Key: session_id, id"
    "                          ->  Seq Scan on test  (cost=0.00..29.40 rows=1940 width=12)"
    

    당신이 볼 수 있습니다 : 첫 번째는 처음 세 개의 창 기능을위한 ID에 의해 순서가있다.

    이것은 제공 (질문에 명시된 바와 같이)

    id  window_asc     first_value_window_asc  last_value_window_asc  
    --  -------------  ----------------------  ---------------------  
    3   {900}          900                     900                    
    4   {900,800}      900                     800                    
    5   {900,800,500}  900                     500                    
    0   {100}          100                     100                    
    1   {100,120}      100                     120                    
    2   {100,120,140}  100                     140    
    

    다음 세 가지 윈도우 기능의 ID DESC BY ORDER : 그럼 당신은 다른 종류를 볼 수 있습니다. 이런 종류의 수 있습니다 :

    id  window_asc     first_value_window_asc  last_value_window_asc  
    --  -------------  ----------------------  ---------------------  
    5   {900,800,500}  900                     500                    
    4   {900,800}      900                     800                    
    3   {900}          900                     900                    
    2   {100,120,140}  100                     140                    
    1   {100,120}      100                     120                    
    0   {100}          100                     100                        
    

    이것은 DESC 창 기능을 정렬로 실행됩니다. array_accum 열 쇼 결과 창 :

    id  window_desc    
    --  -------------  
    5   {500}          
    4   {500,800}      
    3   {500,800,900}  
    2   {140}          
    1   {140,120}      
    0   {140,120,100}  
    

    얻어진 (FIRST_VALUE 및 DESC) LAST_VALUE DESC 이제 LAST_VALUE ASC 절대적으로 동일하다 :

    id  window_asc     last_value_window_asc  window_desc    last_value_window_desc  
    --  -------------  ---------------------  -------------  ----------------------  
    5   {900,800,500}  500                    {500}          500                     
    4   {900,800}      800                    {500,800}      800                     
    3   {900}          900                    {500,800,900}  900                     
    2   {100,120,140}  140                    {140}          140                     
    1   {100,120}      120                    {140,120}      120                     
    0   {100}          100                    {140,120,100}  100    
    

    LAST_VALUE ASC는 LAST_VALUE DESC 동일 왜 지금은 나에게 분명 해졌다. 이는 윈도우 함수의 두 번째 순서는 거꾸로 창을 제공하기 때문이다.

    (문장의 마지막 주문 BY IST 실행 계획의 마지막 종류.)

    이 쿼리 쇼 약간의 최적화 가능성 : 약간의 보너스로 먼저 다음 ASC의 사람을 DESC 창을 호출하는 경우에는 세 번째 종류의 필요가 없습니다. 그것은이 순간에 적절한 종류입니다.

  3. ==============================

    3.윈도우 프레임이 어떻게 정의되는지 확인합니다. 이 예는 도움이 될 수 있습니다 :

    윈도우 프레임이 어떻게 정의되는지 확인합니다. 이 예는 도움이 될 수 있습니다 :

    select 
        id,
        last_value(value) over (
            partition by session_id
            order by id
        ) as lv_asc,
        last_value(value) over (
            partition by session_id
            order by id desc
        ) as lv_desc,
        last_value(value) over (
            partition by session_id
            order by id
            rows between unbounded preceding and unbounded following
        ) as lv_asc_unbounded,
        last_value(value) over (
            partition by session_id
            order by id desc
            rows between unbounded preceding and unbounded following
        ) as lv_desc_unbounded
    from t
    order by id;
     id | lv_asc | lv_desc | lv_asc_unbounded | lv_desc_unbounded 
    ----+--------+---------+------------------+-------------------
      0 |    100 |     100 |              140 |               100
      1 |    120 |     120 |              140 |               100
      2 |    140 |     140 |              140 |               100
      3 |    900 |     900 |              500 |               900
      4 |    800 |     800 |              500 |               900
      5 |    500 |     500 |              500 |               900
    
  4. from https://stackoverflow.com/questions/42299101/window-functions-last-valueorder-by-asc-same-as-last-valueorder-by-d by cc-by-sa and MIT license