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

좋은 웹페이지 즐겨찾기