UNNEST를 이용하여 패턴별 처리를 짧게 기술
이게 뭐야
UNNEST의 여러 사용법을 결합하여 SQL을 크게 짧게 작성하는 방법을 소개합니다.
과제 설정
사용자 u
각 2열 패턴 t1
, t2
및 값 v
가 있는 로그가 있다고 가정합니다.
유저×패턴마다, 그 패턴의 로그수가 유저의 로그수 전체에 차지하는 비율을 계산하고 싶습니다.
예를 들어,
- u=1, t1=a 의 로그가 u=1 의 로그 전체에서 차지하는 비율은 1/2
- u=1, t1=a, t2=p의 로그가 u=1의 로그 전체에서 차지하는 비율은 1/2
- u=1, t1=a, t2=q의 로그가 u=1의 로그 전체에서 차지하는 비율은 0
- u=3, t2=q의 로그가 u=3의 로그 전체에서 차지하는 비율은 1
같은 상태입니다.
패턴 조합은{a/b/both} × {p/q/both} - 1 = 3×3-1 = 8
됩니다.
해결책 1: 가로로 집계한 다음 세로로 바꾸기
어리석게 8 패턴을 내보냅니다.
옆으로 집계를 한 후, UNNEST에 의한 크로스 곱을 이용하여 세로로 바꿉니다.
WITH df AS (
SELECT 1 AS u, "a" AS t1, "p" AS t2, "x" AS v
UNION ALL SELECT 1 AS u, "b" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "z" AS v
UNION ALL SELECT 3 AS u, "b" AS t1, "q" AS t2, "z" AS v
)
,
df_extend AS (
SELECT
u
, COUNTIF(t1="a") / COUNT(*) AS t1a
, COUNTIF(t1="b") / COUNT(*) AS t1b
, COUNTIF(t2="p") / COUNT(*) AS t2p
, COUNTIF(t2="q") / COUNT(*) AS t2q
, COUNTIF(t1="a" AND t2="p") / COUNT(*) AS t1at2p
, COUNTIF(t1="a" AND t2="q") / COUNT(*) AS t1at2q
, COUNTIF(t1="b" AND t2="p") / COUNT(*) AS t1bt2p
, COUNTIF(t1="b" AND t2="q") / COUNT(*) AS t1bt2q
FROM
df
GROUP BY
u
)
SELECT
u
, type
, CASE type
WHEN "t1a" THEN t1a
WHEN "t1b" THEN t1b
WHEN "t2p" THEN t2p
WHEN "t2q" THEN t2q
WHEN "t1at2p" THEN t1at2p
WHEN "t1at2q" THEN t1at2q
WHEN "t1bt2p" THEN t1bt2p
WHEN "t1bt2q" THEN t1bt2q
END AS value
FROM
df_extend, UNNEST(["t1at2p", "t1at2q", "t1a", "t1bt2p", "t1bt2q", "t1b", "t2p", "t2q"]) AS type
출력 결과 (발췌)
사용자 × 패턴마다 해당 패턴의 로그가 전체 사용자의 로그에서 차지하는 비율이 계산되었습니다.
문제
이번 경우는 패턴수가 8 패턴이므로 개별 패턴을 SQL 쿼리 안에 모두 내보내도 허용할 수 있습니다.
그러나, 예를 들어 t1이 9종류, t2가 49종류 있는 경우, 조합은 (9+1)*(49+1)-1=499
종류가 되어, 개개의 패턴을 SQL 쿼리안에 써내는 것은 현실적이지 않습니다.
고행이고, 실수를 낳기 쉽고, 개수도 괴롭습니다.
해결책 2: UNNEST를 최대한 활용하여 처음부터 수직으로 집계
UNNEST를 이용합니다.
WITH df AS (
SELECT 1 AS u, "a" AS t1, "p" AS t2, "x" AS v
UNION ALL SELECT 1 AS u, "b" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "z" AS v
UNION ALL SELECT 3 AS u, "b" AS t1, "q" AS t2, "z" AS v
)
SELECT
u
, v1
, v2
, COUNTIF(t1=v1 AND t2=v2) / (COUNTIF(t1="all" AND t2="all")) AS rate
FROM
df
, UNNEST([t1, "all"]) AS t1
, UNNEST([t2, "all"]) AS t2
, UNNEST(["a", "b", "all"]) AS v1
, UNNEST(["p", "q", "all"]) AS v2
GROUP BY
u, v1, v2
HAVING
NOT(v1 = "all" AND v2 = "all") -- 全てallのパターンは要らないので取り除く
출력 결과 (발췌)
UNNEST([カラム名 + "all"])
라고 하는 것으로, 컬럼명만을 "all"로 바꾼 데이터를 재차 호출할 수가 있습니다.
이를 활용하면 집계 쿼리가 크게 짧아졌습니다.
요약
UNNEST를 다루는 것으로, 패턴마다의 처리를 짧게 기술할 수 있었습니다.
Reference
이 문제에 관하여(UNNEST를 이용하여 패턴별 처리를 짧게 기술), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/hanon/items/3f3e37e61073fd6c1ba1
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
사용자
u
각 2열 패턴 t1
, t2
및 값 v
가 있는 로그가 있다고 가정합니다.유저×패턴마다, 그 패턴의 로그수가 유저의 로그수 전체에 차지하는 비율을 계산하고 싶습니다.
예를 들어,
- u=1, t1=a 의 로그가 u=1 의 로그 전체에서 차지하는 비율은 1/2
- u=1, t1=a, t2=p의 로그가 u=1의 로그 전체에서 차지하는 비율은 1/2
- u=1, t1=a, t2=q의 로그가 u=1의 로그 전체에서 차지하는 비율은 0
- u=3, t2=q의 로그가 u=3의 로그 전체에서 차지하는 비율은 1
같은 상태입니다.
패턴 조합은
{a/b/both} × {p/q/both} - 1 = 3×3-1 = 8
됩니다.해결책 1: 가로로 집계한 다음 세로로 바꾸기
어리석게 8 패턴을 내보냅니다.
옆으로 집계를 한 후, UNNEST에 의한 크로스 곱을 이용하여 세로로 바꿉니다.
WITH df AS (
SELECT 1 AS u, "a" AS t1, "p" AS t2, "x" AS v
UNION ALL SELECT 1 AS u, "b" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "z" AS v
UNION ALL SELECT 3 AS u, "b" AS t1, "q" AS t2, "z" AS v
)
,
df_extend AS (
SELECT
u
, COUNTIF(t1="a") / COUNT(*) AS t1a
, COUNTIF(t1="b") / COUNT(*) AS t1b
, COUNTIF(t2="p") / COUNT(*) AS t2p
, COUNTIF(t2="q") / COUNT(*) AS t2q
, COUNTIF(t1="a" AND t2="p") / COUNT(*) AS t1at2p
, COUNTIF(t1="a" AND t2="q") / COUNT(*) AS t1at2q
, COUNTIF(t1="b" AND t2="p") / COUNT(*) AS t1bt2p
, COUNTIF(t1="b" AND t2="q") / COUNT(*) AS t1bt2q
FROM
df
GROUP BY
u
)
SELECT
u
, type
, CASE type
WHEN "t1a" THEN t1a
WHEN "t1b" THEN t1b
WHEN "t2p" THEN t2p
WHEN "t2q" THEN t2q
WHEN "t1at2p" THEN t1at2p
WHEN "t1at2q" THEN t1at2q
WHEN "t1bt2p" THEN t1bt2p
WHEN "t1bt2q" THEN t1bt2q
END AS value
FROM
df_extend, UNNEST(["t1at2p", "t1at2q", "t1a", "t1bt2p", "t1bt2q", "t1b", "t2p", "t2q"]) AS type
출력 결과 (발췌)
사용자 × 패턴마다 해당 패턴의 로그가 전체 사용자의 로그에서 차지하는 비율이 계산되었습니다.
문제
이번 경우는 패턴수가 8 패턴이므로 개별 패턴을 SQL 쿼리 안에 모두 내보내도 허용할 수 있습니다.
그러나, 예를 들어 t1이 9종류, t2가 49종류 있는 경우, 조합은 (9+1)*(49+1)-1=499
종류가 되어, 개개의 패턴을 SQL 쿼리안에 써내는 것은 현실적이지 않습니다.
고행이고, 실수를 낳기 쉽고, 개수도 괴롭습니다.
해결책 2: UNNEST를 최대한 활용하여 처음부터 수직으로 집계
UNNEST를 이용합니다.
WITH df AS (
SELECT 1 AS u, "a" AS t1, "p" AS t2, "x" AS v
UNION ALL SELECT 1 AS u, "b" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "z" AS v
UNION ALL SELECT 3 AS u, "b" AS t1, "q" AS t2, "z" AS v
)
SELECT
u
, v1
, v2
, COUNTIF(t1=v1 AND t2=v2) / (COUNTIF(t1="all" AND t2="all")) AS rate
FROM
df
, UNNEST([t1, "all"]) AS t1
, UNNEST([t2, "all"]) AS t2
, UNNEST(["a", "b", "all"]) AS v1
, UNNEST(["p", "q", "all"]) AS v2
GROUP BY
u, v1, v2
HAVING
NOT(v1 = "all" AND v2 = "all") -- 全てallのパターンは要らないので取り除く
출력 결과 (발췌)
UNNEST([カラム名 + "all"])
라고 하는 것으로, 컬럼명만을 "all"로 바꾼 데이터를 재차 호출할 수가 있습니다.
이를 활용하면 집계 쿼리가 크게 짧아졌습니다.
요약
UNNEST를 다루는 것으로, 패턴마다의 처리를 짧게 기술할 수 있었습니다.
Reference
이 문제에 관하여(UNNEST를 이용하여 패턴별 처리를 짧게 기술), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/hanon/items/3f3e37e61073fd6c1ba1
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
WITH df AS (
SELECT 1 AS u, "a" AS t1, "p" AS t2, "x" AS v
UNION ALL SELECT 1 AS u, "b" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "z" AS v
UNION ALL SELECT 3 AS u, "b" AS t1, "q" AS t2, "z" AS v
)
,
df_extend AS (
SELECT
u
, COUNTIF(t1="a") / COUNT(*) AS t1a
, COUNTIF(t1="b") / COUNT(*) AS t1b
, COUNTIF(t2="p") / COUNT(*) AS t2p
, COUNTIF(t2="q") / COUNT(*) AS t2q
, COUNTIF(t1="a" AND t2="p") / COUNT(*) AS t1at2p
, COUNTIF(t1="a" AND t2="q") / COUNT(*) AS t1at2q
, COUNTIF(t1="b" AND t2="p") / COUNT(*) AS t1bt2p
, COUNTIF(t1="b" AND t2="q") / COUNT(*) AS t1bt2q
FROM
df
GROUP BY
u
)
SELECT
u
, type
, CASE type
WHEN "t1a" THEN t1a
WHEN "t1b" THEN t1b
WHEN "t2p" THEN t2p
WHEN "t2q" THEN t2q
WHEN "t1at2p" THEN t1at2p
WHEN "t1at2q" THEN t1at2q
WHEN "t1bt2p" THEN t1bt2p
WHEN "t1bt2q" THEN t1bt2q
END AS value
FROM
df_extend, UNNEST(["t1at2p", "t1at2q", "t1a", "t1bt2p", "t1bt2q", "t1b", "t2p", "t2q"]) AS type
이번 경우는 패턴수가 8 패턴이므로 개별 패턴을 SQL 쿼리 안에 모두 내보내도 허용할 수 있습니다.
그러나, 예를 들어 t1이 9종류, t2가 49종류 있는 경우, 조합은
(9+1)*(49+1)-1=499
종류가 되어, 개개의 패턴을 SQL 쿼리안에 써내는 것은 현실적이지 않습니다.고행이고, 실수를 낳기 쉽고, 개수도 괴롭습니다.
해결책 2: UNNEST를 최대한 활용하여 처음부터 수직으로 집계
UNNEST를 이용합니다.
WITH df AS (
SELECT 1 AS u, "a" AS t1, "p" AS t2, "x" AS v
UNION ALL SELECT 1 AS u, "b" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "z" AS v
UNION ALL SELECT 3 AS u, "b" AS t1, "q" AS t2, "z" AS v
)
SELECT
u
, v1
, v2
, COUNTIF(t1=v1 AND t2=v2) / (COUNTIF(t1="all" AND t2="all")) AS rate
FROM
df
, UNNEST([t1, "all"]) AS t1
, UNNEST([t2, "all"]) AS t2
, UNNEST(["a", "b", "all"]) AS v1
, UNNEST(["p", "q", "all"]) AS v2
GROUP BY
u, v1, v2
HAVING
NOT(v1 = "all" AND v2 = "all") -- 全てallのパターンは要らないので取り除く
출력 결과 (발췌)
UNNEST([カラム名 + "all"])
라고 하는 것으로, 컬럼명만을 "all"로 바꾼 데이터를 재차 호출할 수가 있습니다.
이를 활용하면 집계 쿼리가 크게 짧아졌습니다.
요약
UNNEST를 다루는 것으로, 패턴마다의 처리를 짧게 기술할 수 있었습니다.
Reference
이 문제에 관하여(UNNEST를 이용하여 패턴별 처리를 짧게 기술), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다
https://qiita.com/hanon/items/3f3e37e61073fd6c1ba1
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념
(Collection and Share based on the CC Protocol.)
WITH df AS (
SELECT 1 AS u, "a" AS t1, "p" AS t2, "x" AS v
UNION ALL SELECT 1 AS u, "b" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "y" AS v
UNION ALL SELECT 2 AS u, "a" AS t1, "p" AS t2, "z" AS v
UNION ALL SELECT 3 AS u, "b" AS t1, "q" AS t2, "z" AS v
)
SELECT
u
, v1
, v2
, COUNTIF(t1=v1 AND t2=v2) / (COUNTIF(t1="all" AND t2="all")) AS rate
FROM
df
, UNNEST([t1, "all"]) AS t1
, UNNEST([t2, "all"]) AS t2
, UNNEST(["a", "b", "all"]) AS v1
, UNNEST(["p", "q", "all"]) AS v2
GROUP BY
u, v1, v2
HAVING
NOT(v1 = "all" AND v2 = "all") -- 全てallのパターンは要らないので取り除く
UNNEST를 다루는 것으로, 패턴마다의 처리를 짧게 기술할 수 있었습니다.
Reference
이 문제에 관하여(UNNEST를 이용하여 패턴별 처리를 짧게 기술), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://qiita.com/hanon/items/3f3e37e61073fd6c1ba1텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)