Snowflake에서 GROUP By/ORDER By 및 열 별칭 처리 순서

안녕하세요, Snowflak에서 지원 엔지니어로 일하고 있습니다.
우선 이것 좀 보세요.
create or replace table t1 (c1 varchar, c2 varchar) as
select * from values ('1', 'one'), ('1', 'odin');

select c1::int c1, array_agg(c2), grouping(c1) from t1
group by grouping sets (c1, c2)
order by grouping(c1) desc;
Snowflake를 사용한 경우 결과는 다음과 같습니다.
C1	ARRAY_AGG(C2)	GROUPING(C1)
1	["one", "odin"]	0
NULL	["one"]		1
NULL	["odin"]	1
GROUPING(C1) 즉 내림차순으로 정렬되었음에도 불구하고 왠지 0→1의 순서, 즉 오름차순으로 정렬되었다.
언뜻 보기에는 결과가 정확하지 않은 것 같지만, 사실은 직감으로만 스노우플러그가 정확하게 처리되었다.
이 문장에서 우리는 왜 이 출력이 정확한지 설명할 것이다.
(본 기사는 소속 조직의 공식 견해가 아닌 개인 실천의 공유입니다.)

전제: GRUPING()은 무엇입니까?


그 전에 말씀드리고 싶습니다DESC.GROUPING()는 열 이름이나 유사한 방정식을 매개 변수로 삼아 0(집합) 또는 1(집합되지 않음)으로'이 줄이 이 열(또는 표현식)으로 집합되는지 여부'를 되돌려줍니다.
https://docs.snowflake.com/ja/sql-reference/functions/grouping.html
GRUPING(식)은 <식> 조합을 통과한 줄에 0을, <식> 조합을 통과하지 않은 줄에 대해서는 1을 반환합니다.
상기 조회 중의 총결산GROUPING()GROUP BY GROUPING SETS (C1, C2)C1가 각각 얻은 결과C2가 되돌아오는 형식이다.
따라서 GROUP BYUNION에 모인 줄만 0으로, GROUPING(C1)에 모인 줄은 1로 돌아간다.

원인을 조사하다


결과를 직감적으로 잘못 봤으니 실제로 왜 이런 일이 일어났는지 확인해 보세요.
Snowflak은 모든 질의에 대한 Query Profile을 가져오고 일정의 균형을 제공합니다.
우선, 이 검색어의Query 프로필을 살펴봅시다.

간단한 조회이기 때문에 구조가 간단하고 이해하기 쉽다.C1 표에서 데이터를 읽고 C2 총결산(GROUPBY), TableScan 정렬(ORDER BY), GroupingSets 결과를 되돌려줍니다.
또한 이 화면에서 Sort를 선택했기 때문에 각각 Result, Result, TO_NUMBER(T1.C1), ARRAY_AGG(T1.C2)를 결과로 되돌려준다.
그럼 각 단계가 어떻게 움직이는지 확인해 보세요.개별 상자를 클릭하여 작업의 세부내용을 확인할 수 있습니다.GROUPING_ID(T1.C1) :
Sort :

그럼, 잘못된 걸 찾을 시간이네요.참고로 보조 엔지니어를 할 때 오류를 찾는 것은 매우 중요한 능력이다. 단련을 통해 브라우저 화면의 차이가 나타나고 로그를 적당히 굴리면 이상한 행동이 나타난다.
이것은 상당히 간단한 문제다.GroupingSets(=ORDER BY)를 정렬키Sort로 삼았다TO_NUMBER(T1.C1).
단, t1.c1::intResults 함수와 GROUPING()(=GROUPBY) 사용GroupingSets 즉 캐릭터를 분배하기 전의 값이다.
즉, 우리는 상술한 조회가 본질적으로 다음과 같다는 것을 발견했다.T1.C1 따라서 이 검색어ORDER BY문에 있는 GROUPING()의 매개 변수t1.c1::intGROUP BY에서 사용된 t1.c1와 다르기 때문에 모든 줄이'미재t1.c1::int에 집합된 것으로 판정됩니다. 모든 줄이 1로 되돌아오기 때문에 정렬 순서가 정해지지 않습니다.이처럼 잘못 보이는 결과가 보답을 받은 셈이다.
즉, Snowflakカラム名 → GROUP BY → カラムエイリアス → ORDER BY순차적으로 해결된 일은 추측된다.

이유는...


같은 이름의 열 별명c1::int c1.
그래서 c1t1.c1인지 t1.c1::int인지 모르겠다.
예를 들어 MySQL에서 이 동작을 실행할 때c1ambiguous의 경고를 보냅니다.
select
    t1.c1::int,
    array_agg(t1.c2),
    grouping(t1.c1)
from t1
group by grouping sets (t1.c1, t1.c2)
order by grouping(t1.c1::int) desc;
이번처럼 컴파일러는 혼란스러울 뿐만 아니라 SQL의 가독성 자체에도 큰 영향을 미치기 때문에 동명의 열별명을 피하는 것이 좋다.

해결책


가장 간단한 해결 방법은 '열의 별명을 사용하지 않음' 이나 '별명의 별명을 사용하지 않음' 이다.

열 별칭 사용 안 함


mysql> select cast(c1 as signed) c1, group_concat(c2) from t1 group by c1;
+------+------------------+
| c1   | group_concat(c2) |
+------+------------------+
|    1 | one,odin         |
+------+------------------+
1 row in set, 1 warning (0.00 sec)

mysql> show warnings;
+---------+------+---------------------------------------------+
| Level   | Code | Message                                     |
+---------+------+---------------------------------------------+
| Warning | 1052 | Column 'c1' in group statement is ambiguous |
+---------+------+---------------------------------------------+
1 row in set (0.00 sec)
이 경우 모든 시점c1에서 int에 대한 분배 역할이 집행되기 때문에 문제가 없는 일치성 처리이다.

별칭 사용


select c1::int, array_agg(c2), grouping(c1::int) from t1
group by grouping sets (c1::int, c2)
order by grouping(c1::int) desc;
이 경우 c1_new 해결될 때까지 GROUP BY 해결되지 않으므로 처리 순서カラム名 → カラムエイリアス → GROUP BY → ORDER BY변, 문제 해결.

열 유형 변경하기


또한 원래 읽을 때 역할 분배 자체에 의존하는 것은 데이터의 일치성 관점이든 자동주의자의 관점이든 모두 좋은 실천이 아니기 때문에 원본c1열 자체는int여야 한다.
예를 들어 c1varchar라면 Snowflak 수준에서 이 열이 수치 문자열만 저장되었는지 보장할 수 없다.

겸사겸사 말씀드리지만..


아마도 당신이 추측한 바와 같이, 이 동작은 설치에 달려 있을 것입니다.다만 Snowflak이 공교롭게도 이렇게 실행되었을 뿐 다른 데이터베이스도 반드시 같은 동작을 할 수 있는 것은 아니다.(참고로 Oracle은 동일한 동작임)
예를 들어, PostgreSQL은 위의 질의에 대해 직관적인 결과를 반환합니다.
select c1::int c1_new, array_agg(c2), grouping(c1_new) from t1
group by grouping sets (c1_new, c2)
order by grouping(c1_new) desc;

총결산


이 보도의 현상 자체는 겪어보지 못한 동작의 기교에 관한 것일 수도 있고, 알아도 손실이 없을 수도 있지만, 그 자체가 중요한 정보는 아니다.
이 기사에서 전하고 싶은 건요.
  • 언뜻 보기에는 결과가 정확하지 않아도 정확한 동작을 할 수 있다(상당히 많다)
  • Query 소개는 성능 문제뿐만 아니라 결과가 부정확한 문제에도 유용하다
  • 인간 상식을 믿지 않고 조회 컴파일러의 심정을 고려
  • 오류 검색 능력이 중요
  • 그러니까
    나는 조사 결과가 부정확한 결과를 가장 좋아한다. 줄곧 조사 결과가 부정확하다고 생각하기 때문에 여러분의 투표를 기대한다.

    좋은 웹페이지 즐겨찾기