아래 SQL 데이터 이용해서 순서를 변경하지말고 4개 로우 단위로 ENTER_YN 컬럼에 Y 표시 하려고 합니다.
근대 Y 표시 하기전 현재의 로우의 SYMBOL 과 이후 로우의 SYMBOL 이 같으면 N으로 표시하고
다음 로우에 Y으로 표시 합니다. Y 라고 표현 했으면 4개 로우 단위는 조건은 초기화 되어 Y 의 로우가 1이 됩니다.
MOD 함수와 LAG, lead, ROW_NUMBER() 함수를 이용해도 안돼네요, 이런건 SQL로 안될까요?
데이터는 예시이고 실제 DB에는 더 많은 양의 데이터가 있습니다.
실제로 하려는건 LISTAGG 함소로 1줄로 만들고 4개마다 엔터키를 붙여서 내리려고 합니다. 근대 값이 같으면 내리지 않고
다음에 값이 나오면 내릴려고요.
SELECT 'L1' AS SYMBOL FROM DUAL UNION ALL
SELECT 'L1' AS SYMBOL FROM DUAL UNION ALL
SELECT 'N7' AS SYMBOL FROM DUAL UNION ALL
SELECT 'N7' AS SYMBOL FROM DUAL UNION ALL
SELECT 'N7' AS SYMBOL FROM DUAL UNION ALL
SELECT 'T1' AS SYMBOL FROM DUAL UNION ALL
SELECT 'T3' AS SYMBOL FROM DUAL UNION ALL
SELECT 'T4' AS SYMBOL FROM DUAL UNION ALL
SELECT 'T7' AS SYMBOL FROM DUAL UNION ALL
SELECT 'T7' AS SYMBOL FROM DUAL UNION ALL
SELECT 'R1' AS SYMBOL FROM DUAL UNION ALL
SELECT 'R2' AS SYMBOL FROM DUAL UNION ALL
SELECT 'R3' AS SYMBOL FROM DUAL UNION ALL
SELECT 'R4' AS SYMBOL FROM DUAL UNION ALL
SELECT 'Z1' AS SYMBOL FROM DUAL
-- 아래 처럼 나오게.
SYMBOL|ENTER_YN|
------+--------+
L1 | N |
L1 | N |
N7 | N |
N7 | N | -- 4번째 이므로 Y가 되야 하나 다음로우 값이 N7 이므로 N
N7 | Y | -- 4개 로우로 표시를 못햇음로 여기에 Y 표시
T1 | N | -- 여기서 부터 4개로우 단위로 초기화 됨
T3 | N |
T4 | N |
T7 | N | -- 여기에 Y가 되야 하나 다음로우 값이 T7 이므로 N
T7 | Y | -- 4개 로우로 표시를 못햇음로 여기에 Y 표시
R1 | N | -- 여기서 부터 4개로우 단위로 초기화 됨
R2 | N |
R3 | N |
R4 | Y | -- 다음로우 값이 R4 와 다르므로 이므로 Y
Z1 | N |
WITH t AS
(
SELECT 1 seq, 'L1' symbol FROM dual
UNION ALL SELECT 2, 'L1' FROM dual
UNION ALL SELECT 3, 'N7' FROM dual
UNION ALL SELECT 4, 'N7' FROM dual
UNION ALL SELECT 5, 'N7' FROM dual
--UNION ALL SELECT 6, 'N7' FROM dual
UNION ALL SELECT 7, 'T1' FROM dual
UNION ALL SELECT 8, 'T3' FROM dual
UNION ALL SELECT 9, 'T4' FROM dual
UNION ALL SELECT 10, 'T7' FROM dual
UNION ALL SELECT 11, 'T7' FROM dual
UNION ALL SELECT 12, 'R1' FROM dual
UNION ALL SELECT 13, 'R2' FROM dual
UNION ALL SELECT 14, 'R3' FROM dual
UNION ALL SELECT 15, 'R4' FROM dual
UNION ALL SELECT 16, 'Z1' FROM dual
)
, t1 AS
(
SELECT symbol
, LEAD(symbol, 1, 'x') OVER(ORDER BY seq) next_symbol
, ROW_NUMBER() OVER(ORDER BY seq) rn
FROM t
)
, t2(rn, symbol, next_symbol, enter_yn, cnt) AS
(
SELECT rn
, symbol
, next_symbol
, 'N' enter_yn
, 1 cnt
FROM t1
WHERE rn = 1
UNION ALL
SELECT b.rn
, b.symbol
, b.next_symbol
, CASE WHEN a.cnt = 3 AND b.symbol != b.next_symbol THEN 'Y'
ELSE 'N' END enter_yn
, CASE WHEN a.cnt = 4 THEN 1
WHEN a.cnt = 3 AND b.symbol = b.next_symbol THEN 3
ELSE a.cnt + 1 END cnt
FROM t2 a
, t1 b
WHERE b.rn = a.rn + 1
)
SELECT rn
, symbol
, enter_yn
FROM t2
;
질문을 다시 읽어 보니 enter_yn 이 최종목표가 아니네요?
한줄로 묶는 것이 목표라면 enter_yn 을 만드는 것은 비효율적일 것 같습니다.
enter_yn 으로 어떻게 한줄로 만들지 다시 고민하셔야 할 것 같은데요?
아예 처음부터 줄번호(그룹 기준)를 만드는 것이 효율적일 것 같네요.
WITH t AS
(
SELECT 1 seq, 'L1' symbol FROM dual
UNION ALL SELECT 2, 'L1' FROM dual
UNION ALL SELECT 3, 'N7' FROM dual
UNION ALL SELECT 4, 'N7' FROM dual
UNION ALL SELECT 5, 'N7' FROM dual
--UNION ALL SELECT 6, 'N7' FROM dual
UNION ALL SELECT 7, 'T1' FROM dual
UNION ALL SELECT 8, 'T3' FROM dual
UNION ALL SELECT 9, 'T4' FROM dual
UNION ALL SELECT 10, 'T7' FROM dual
UNION ALL SELECT 11, 'T7' FROM dual
UNION ALL SELECT 12, 'R1' FROM dual
UNION ALL SELECT 13, 'R2' FROM dual
UNION ALL SELECT 14, 'R3' FROM dual
UNION ALL SELECT 15, 'R4' FROM dual
UNION ALL SELECT 16, 'Z1' FROM dual
)
, t1 AS
(
SELECT symbol
, ROW_NUMBER() OVER(ORDER BY seq) rn
FROM t
)
, t2(rn, symbol, grp_no, cnt) AS
(
SELECT rn
, symbol
, 1 grp_no
, 1 cnt
FROM t1
WHERE rn = 1
UNION ALL
SELECT b.rn
, b.symbol
, CASE WHEN a.cnt >= 4 AND a.symbol != b.symbol
THEN 1 ELSE 0 END + grp_no
, CASE WHEN a.cnt >= 4 AND a.symbol != b.symbol
THEN 1
ELSE a.cnt + 1 END cnt
FROM t2 a
, t1 b
WHERE b.rn = a.rn + 1
)
SELECT rn
, symbol
, grp_no
FROM t2
;