복붙노트

[SQL] 테이블에서 '다음'과 '이전'에 대한 SQL은 무엇인가?

SQL

테이블에서 '다음'과 '이전'에 대한 SQL은 무엇인가?

나는 그와 관련된 날짜가 각각의 항목의 테이블을 가지고있다. 나는 날짜가 하나 개의 항목과 관련된 경우, 어떻게 SQL을 사용하여 데이터베이스 테이블의 '이전'과 '이후'아이템을 얻을 수 쿼리합니까?

이 날짜는 그들 사이에 일정한 간격을 가지고 있지 않는 한 단순히 값을 추가 (또는 빼기) 할 수 없습니다.

한 가지 가능한 응용 프로그램은 기본 데이터는 SQL 테이블에있는 사진 앨범 또는 블로그 웹 응용 프로그램에서 '이전 / 다음'링크 될 것입니다.

나는 두 가지 경우가 있다고 생각합니다 :

우선 각 날짜는 독특한입니다 :

샘플 데이터 :

1,3,8,19,67,45

매개 변수로 팔을 공급하면 어떻게 쿼리 (또는 쿼리)을 3 줄, 19 것인가? (또는 행 3,8,19). 반환되는 세 개의 행이 항상 아니라는 것을 참고 - 시퀀스 하나의 끝이 누락 될 것이다.

에 의해 요소를 주문하기 위해 별도의 고유 키가있는 경우 둘째, 날짜를 '주변'세트를 반환하는 쿼리는 무엇인가? 예상 순서는 다음 주요 날짜입니다.

샘플 데이터 :

(key:date) 1:1,2:3,3:8,4:8,5:19,10:19,11:67,15:45,16:8

'8'에 대한 어떤 쿼리 집합을 반환합니다 :

2:3,3:8,4:8,16:8,5:19

또는 어떤 쿼리하면 테이블을 생성합니다 :

key date prev-key next-key
1   1    null     2
2   3    1        3
3   8    2        4
4   8    3        16
5   19   16       10
10  19   5        11
11  67   10       15
15  45   11       null
16  8    4        5

테이블 순서는 중요하지 않습니다 - 단지 옆에 키와 이전 키 필드.

TheSoftwareJedi 및 케이드 루는 모두 데이터 세트에 대한 작업 어젯밤에 게시하는 것이 해결책이있다. 두 번째 질문에 대해 모두이 데이터 집합에 대한 실패 할 것 같다 :

(key:date) 1:1,2:3,3:8,4:8,5:19,10:19,11:67,15:45,16:8

하나 개의 예상 결과가 될 수 있도록 기대 순서는 날짜를 기준으로 다음 열쇠입니다 :

2:3,3:8,4:8,16:8,5:19

그리고 또 다른:

key date prev-key next-key
1   1    null     2
2   3    1        3
3   8    2        4
4   8    3        16
5   19   16       10
10  19   5        11
11  67   10       15
15  45   11       null
16  8    4        5

테이블 순서는 중요하지 않습니다 - 단지 옆에 키와 이전 키 필드.

해결법

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

    1.데이터에서 선택 최대 (요소) 요소 <8

    데이터에서 선택 최대 (요소) 요소 <8

    노동 조합

    데이터에서 분 (요소)를 선택 어디 요소> (8)

    그러나 일반적으로는 세트 지향적 인 작업보다는 반복적 인 작업에 SQL 생각하는 것이 더 유용하다.

  2. ==============================

    2.셀프 조인.

    셀프 조인.

    테이블의 경우 :

    /*
    CREATE TABLE [dbo].[stackoverflow_203302](
        [val] [int] NOT NULL
    ) ON [PRIMARY]
    */
    

    와 매개 변수 @val

    SELECT cur.val, MAX(prv.val) AS prv_val, MIN(nxt.val) AS nxt_val
    FROM stackoverflow_203302 AS cur
    LEFT JOIN stackoverflow_203302 AS prv
        ON cur.val > prv.val
    LEFT JOIN stackoverflow_203302 AS nxt
        ON cur.val < nxt.val
    WHERE cur.val = @val
    GROUP BY cur.val
    

    이 출력 매개 변수를 사용하여 저장 프로 시저를 만들거나 당신이 당기는 데이터에 상관 하위 쿼리로이 가입 할 수있다.

    매개 변수가 없으면, 데이터에 대한 결과는 다음과 같습니다

    val         prv_val     nxt_val
    ----------- ----------- -----------
    1           NULL        3
    3           1           8
    8           3           19
    19          8           45
    45          19          67
    67          45          NULL
    

    수정 된 예를 들어, 당신은 상관 하위 쿼리로 사용 :

    /*
    CREATE TABLE [dbo].[stackoverflow_203302](
        [ky] [int] NOT NULL,
        [val] [int] NOT NULL,
        CONSTRAINT [PK_stackoverflow_203302] PRIMARY KEY CLUSTERED (
            [ky] ASC
        )
    )
    */
    
    SELECT cur.ky AS cur_ky
            ,cur.val AS cur_val
            ,prv.ky AS prv_ky
            ,prv.val AS prv_val
            ,nxt.ky AS nxt_ky
            ,nxt.val as nxt_val
    FROM (
        SELECT cur.ky, MAX(prv.ky) AS prv_ky, MIN(nxt.ky) AS nxt_ky
        FROM stackoverflow_203302 AS cur
        LEFT JOIN stackoverflow_203302 AS prv
            ON cur.ky > prv.ky
        LEFT JOIN stackoverflow_203302 AS nxt
            ON cur.ky < nxt.ky
        GROUP BY cur.ky
    ) AS ordering
    INNER JOIN stackoverflow_203302 as cur
        ON cur.ky = ordering.ky
    LEFT JOIN stackoverflow_203302 as prv
        ON prv.ky = ordering.prv_ky
    LEFT JOIN stackoverflow_203302 as nxt
        ON nxt.ky = ordering.nxt_ky
    

    출력 예상대로 :

    cur_ky      cur_val     prv_ky      prv_val     nxt_ky      nxt_val
    ----------- ----------- ----------- ----------- ----------- -----------
    1           1           NULL        NULL        2           3
    2           3           1           1           3           8
    3           8           2           3           4           19
    4           19          3           8           5           67
    5           67          4           19          6           45
    6           45          5           67          NULL        NULL
    

    SQL Server에서 나는 서브 쿼리 공통 테이블 식 수 있도록하는 것을 선호합니다. 이 코드는 중첩이 많이있을 경우에 따라, 더욱 선형 적은 중첩 쉽게 보일 수 있습니다 (또한, 적은 반복 일부가 다시 조인에 필요합니다).

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

    3.첫째,이 일을해야합니다 (ORDER BY 중요하다)

    첫째,이 일을해야합니다 (ORDER BY 중요하다)

    select min(a)
    from theTable
    where a > 8
    
    select max(a)
    from theTable
    where a < 8
    

    두 번째 질문에 대한 물어 당신을 구걸 ... :

        select * 
        from theTable
        where date = 8
    
        union all
    
        select *
        from theTable
        where key = (select min(key) 
                     from theTable
                     where key > (select max(key)
                                  from theTable
                                  where date = 8)
                    )
    
        union all
    
        select *
        from theTable
        where key = (select max(key) 
                     from theTable
                     where key < (select min(key)
                                  from theTable
                                  where date = 8)
                    )
    
        order by key
    
  4. ==============================

    4.

    SELECT 'next' AS direction, MIN(date_field) AS date_key
    FROM table_name
      WHERE date_field > current_date
    GROUP BY 1 -- necessity for group by varies from DBMS to DBMS in this context
    UNION
    SELECT 'prev' AS direction, MAX(date_field) AS date_key
      FROM table_name
      WHERE date_field < current_date
    GROUP BY 1
    ORDER BY 1 DESC;
    

    생성합니다 :

    direction  date_key
    ---------  --------
    prev              3
    next             19
    
  5. ==============================

    5.TheSoftwareJedi에 따라 설정된 솔루션에서 내 자신의 시도.

    TheSoftwareJedi에 따라 설정된 솔루션에서 내 자신의 시도.

    첫 번째 질문 :

    select date from test where date = 8
    union all
    select max(date) from test where date < 8
    union all
    select min(date) from test where date > 8
    order by date;
    

    두 번째 질문 :

    이 디버깅하는 동안, 나는 데이터 세트를 사용 :

    (key:date) 1:1,2:3,3:8,4:8,5:19,10:19,11:67,15:45,16:8,17:3,18:1
    

    이 결과를 제공합니다 :

    select * from test2 where date = 8
    union all
    select * from (select * from test2
                       where date = (select max(date) from test2 
                                         where date < 8)) 
        where key = (select max(key) from test2 
                        where date = (select max(date) from test2 
                                          where date < 8))
    union all
    select * from (select * from test2
                       where date = (select min(date) from test2 
                                         where date > 8)) 
        where key = (select min(key) from test2 
                        where date = (select min(date) from test2 
                                          where date > 8))
    order by date,key;
    

    두 경우 모두 절에 ​​의해 마지막 순서는 엄격하게 옵션 말하고있다.

  6. ==============================

    6.당신의 RDBMS가 지원 LAG와 LEAD 경우,이 간단 (오라클, PostgreSQL을, 2012 SQL 서버)

    당신의 RDBMS가 지원 LAG와 LEAD 경우,이 간단 (오라클, PostgreSQL을, 2012 SQL 서버)

    다음은 단일 쿼리에서 특정 행의 행 양쪽을 선택할 수

  7. ==============================

    7.이 시도...

    이 시도...

    SELECT TOP 3 * FROM YourTable
    WHERE Col >= (SELECT MAX(Col) FROM YourTable b WHERE Col < @Parameter)
    ORDER BY Col
    
  8. from https://stackoverflow.com/questions/203302/what-is-the-sql-for-next-and-previous-in-a-table by cc-by-sa and MIT license