SQL에서 하나의 레코드를 특정 값으로 구분하여 레코드를 복제하고 싶습니다.
개요
타이틀대로이지만, 어휘력이 너무 없어서 말로 자세하게 설명하는 것이 어려웠기 때문에 예로 설명.
예
아래와 같은 데이터가
이것을 아래와 같이 100마다 구분하여 분해하고 싶다.
또한 나머지는 그대로 나머지를 출력하고 싶다.
과연 어떻게 하는 것이 좋은가?
나름대로 도착한 대답
WITH data AS (
SELECT
*
FROM
UNNEST([STRUCT(1 AS user_id, 232 AS amount), (2, 310), (3, 100), (4, 1)])
)
SELECT
user_id,
amount
FROM (
SELECT
user_id,
ARRAY_CONCAT(ARRAY(SELECT 100 FROM UNNEST(GENERATE_ARRAY(1, CAST(TRUNC(amount / 100) AS INT64)))), [MOD(amount, 100)]) AS amount_array
FROM
data
),
UNNEST(amount_array) AS amount
WHERE
amount != 0
해설
간단히 설명하면, 원이 되는 값을 분할해 분할수를 구해 그 분할수분의 요소가 100의 배열을 작성해 그에 대해, 원이 되는 값을 분할했을 때의 나머지를 더해 UNNEST CROSS JOIN으로 전개하고 있다.
라고 해도 잘 모르기 때문에 하나씩 분해
1
GENERATE_ARRAY(1, CAST(TRUNC(amount / 100) AS INT64))
원래 값(amount)을 분할하고자 하는 숫자(100)로 나누어 소수점을 잘라낸다.
예를 들어 378이면 3이 돌아오고, 1이면 0이 돌아온다.
GENERATE_ARRAY(1,n)
는 1에서 n까지의 일련의 배열을 만들어 주기 때문에 여기에서 요소 몇 분의 배열을 작성한다.378→[1,2,3]
2
ARRAY(SELECT 100 FROM UNNEST([1,2,3,4]))
배열의 각 요소를 모두 분할하려는 숫자 (100)로 바꿉니다.
[1,2,3] → [100,100,100]
3
ARRAY_CONCAT([100,100,100], [MOD(amount, 100)])
그 배열에 기초가 되는 값(amount)을 분할하고 싶은 숫자(100)로 나눈 때의 나머지를 추가한다
[100,100,100]→[100,100,100,78]
4
후에는 배열을 UNNEST한 녀석과 원래의 데이터를
CROSS JOIN
해 주면 요구하고 싶은 것이 완성된다.요약
더 똑똑한 방법은 있을지도 모른다, 라고 하는지 있는 엽기가 한다.
다만, UDF를 사용하는 방법은 퍼포먼스 떨어지기 때문에 그다지 하고 싶지 않았다.
Reference
이 문제에 관하여(SQL에서 하나의 레코드를 특정 값으로 구분하여 레코드를 복제하고 싶습니다.), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/tuta_san/items/d951f3dc18002c2dc52c텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)