Snowflake에서 GROUP By/ORDER By 및 열 별칭 처리 순서
우선 이것 좀 보세요.
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(집합되지 않음)으로'이 줄이 이 열(또는 표현식)으로 집합되는지 여부'를 되돌려줍니다.GRUPING(식)은 <식> 조합을 통과한 줄에 0을, <식> 조합을 통과하지 않은 줄에 대해서는 1을 반환합니다.
상기 조회 중의 총결산
GROUPING()
은 GROUP BY GROUPING SETS (C1, C2)
과 C1
가 각각 얻은 결과C2
가 되돌아오는 형식이다.따라서
GROUP BY
는 UNION
에 모인 줄만 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::int
의 Results
함수와 GROUPING()
(=GROUPBY) 사용GroupingSets
즉 캐릭터를 분배하기 전의 값이다.즉, 우리는 상술한 조회가 본질적으로 다음과 같다는 것을 발견했다.
T1.C1
따라서 이 검색어ORDER BY
문에 있는 GROUPING()
의 매개 변수t1.c1::int
는 GROUP BY
에서 사용된 t1.c1
와 다르기 때문에 모든 줄이'미재t1.c1::int
에 집합된 것으로 판정됩니다. 모든 줄이 1로 되돌아오기 때문에 정렬 순서가 정해지지 않습니다.이처럼 잘못 보이는 결과가 보답을 받은 셈이다.즉, Snowflak
カラム名 → GROUP BY → カラムエイリアス → ORDER BY
순차적으로 해결된 일은 추측된다.이유는...
같은 이름의 열 별명
c1::int c1
.그래서
c1
가 t1.c1
인지 t1.c1::int
인지 모르겠다.예를 들어 MySQL에서 이 동작을 실행할 때
c1
ambiguous의 경고를 보냅니다.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
여야 한다.예를 들어
c1
가 varchar
라면 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;
총결산
이 보도의 현상 자체는 겪어보지 못한 동작의 기교에 관한 것일 수도 있고, 알아도 손실이 없을 수도 있지만, 그 자체가 중요한 정보는 아니다.
이 기사에서 전하고 싶은 건요.
나는 조사 결과가 부정확한 결과를 가장 좋아한다. 줄곧 조사 결과가 부정확하다고 생각하기 때문에 여러분의 투표를 기대한다.
Reference
이 문제에 관하여(Snowflake에서 GROUP By/ORDER By 및 열 별칭 처리 순서), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://zenn.dev/indigo13love/articles/cd303636119ad4텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)