SQL에서 하나의 레코드를 특정 값으로 구분하여 레코드를 복제하고 싶습니다.

5157 단어 SQLBigQuery

개요



타이틀대로이지만, 어휘력이 너무 없어서 말로 자세하게 설명하는 것이 어려웠기 때문에 예로 설명.

예



아래와 같은 데이터가



이것을 아래와 같이 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를 사용하는 방법은 퍼포먼스 떨어지기 때문에 그다지 하고 싶지 않았다.

좋은 웹페이지 즐겨찾기