SnowConvert: Teradata DML 문¶
Delete 문¶
Delete 문 참조
Teradata는 FROM
절에서 둘 이상의 테이블 호출을 지원하지만, Snowflake는 지원하지 않습니다. 따라서 조건에 관련된 추가 테이블을 참조하려면 USING
절을 사용해야 합니다.
Teradata
DEL FROM MY_TABLE ALL;
DEL FROM MY_TABLE_2 WHERE COL1 > 50;
DELETE T1 FROM TABLE1 T1, TABLE2 T2 WHERE T1.ID = T2.ID;
DELETE FROM TABLE1 T1, TABLE2 T2 WHERE T1.ID = T2.ID;
DELETE T1 FROM TABLE2 T2, TABLE1 T1 WHERE T1.ID = T2.ID;
DELETE FROM TABLE1 WHERE TABLE1.COLUMN1 = TABLE2.COLUMN2
Snowflake
DELETE FROM
MY_TABLE;
DELETE FROM
MY_TABLE_2
WHERE
COL1 > 50;
DELETE FROM
TABLE1 T1
USING TABLE2 T2
WHERE
T1.ID = T2.ID;
DELETE FROM
TABLE1 T1
USING TABLE2 T2
WHERE
T1.ID = T2.ID;
DELETE FROM
TABLE1 T1
USING TABLE2 T2
WHERE
T1.ID = T2.ID;
DELETE FROM
TABLE1
WHERE
TABLE1.COLUMN1 = TABLE2.COLUMN2;
Known Issues¶
1. DEL abbreviation unsupported¶
이 약어는 Snowflake에서 지원되지 않지만, DELETE 로 변경하면 올바르게 변환됩니다.
세트 연산자¶
참고
출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.
Set 연산자 참조
Teradata와 Snowflake의 Set 연산자는 EXCEPT
, INTERSECT
, UNION
에서 ALL
절을 제외하고는 구문과 지원 시나리오가 동일하며, INTERSECTALL
에서는 지원하지 않으므로 변환 후 ALL
의 일부가 주석 처리된 코드가 됩니다.
Teradata
SELECT LastName, FirstName FROM employees
INTERSECT
SELECT FirstName, LastName FROM contractors;
SELECT LastName, FirstName FROM employees
INTERSECT ALL
SELECT FirstName, LastName FROM contractors;
Snowflake
SELECT
LastName,
FirstName FROM
employees
INTERSECT
SELECT
FirstName,
LastName FROM
contractors;
SELECT
LastName,
FirstName FROM
employees
INTERSECT
!!!RESOLVE EWI!!! /*** SSC-EWI-0040 - THE STATEMENT IS NOT SUPPORTED IN SNOWFLAKE ***/!!! ALL
SELECT
FirstName,
LastName FROM
contractors;
Known Issues¶
1. INTERSECT ALL unsupported¶
INTERSECTALL 은 Snowflake에서 지원되지 않으며 ALL 부분에 설명이 추가됩니다.
관련 EWIs¶
SSC-EWI-0040: 문은 지원되지 않습니다.
Update 문¶
Update 문 참조
Teradata는 별칭을 선언하기 전에 참조하는 기능을 지원하지만, Snowflake는 지원하지 않습니다. 이 시나리오의 변환은 참조된 테이블을 가져와서 참조하는 테이블 이름의 별칭을 변경하는 것입니다.
Teradata
-- Case 1, THERE IS A REFERENCE TO TABLE2 IN THE SET CLAUSE WITHOUT A FROM
UPDATE CRASHDUMPS.TABLE1 i
SET COLUMN4 = CRASHDUMPS.TABLE2.COLUMN3
WHERE i.COLUMN1 = CRASHDUMPS.TABLE2.COLUMN1
AND i.COLUMN3 = 'L';
-- CASE 2, FORWARD ALIAS
UPDATE i
FROM CRASHDUMPS.TABLE2, CRASHDUMPS.TABLE1 i
SET COLUMN4 = CRASHDUMPS.TABLE2.COLUMN3
WHERE i.COLUMN1 = CRASHDUMPS.TABLE2.COLUMN1
AND i.COLUMN3 = 'L';
Snowflake
-- Case 1, THERE IS A REFERENCE TO TABLE2 IN THE SET CLAUSE WITHOUT A FROM
UPDATE CRASHDUMPS.PUBLIC.TABLE1 AS i
SET i.COLUMN4 = CRASHDUMPS.TABLE2.COLUMN3
WHERE i.COLUMN1 = CRASHDUMPS.TABLE2.COLUMN1
AND i.COLUMN3 = 'L';
-- CASE 2, FORWARD ALIAS
UPDATE CRASHDUMPS.PUBLIC.TABLE1 AS i
SET i.COLUMN4 = CRASHDUMPS.TABLE2.COLUMN3 FROM CRASHDUMPS.PUBLIC.TABLE2
WHERE i.COLUMN1 = CRASHDUMPS.TABLE2.COLUMN1
AND i.COLUMN3 = 'L';
관련 EWIs¶
관련 EWIs 없음.
With Modifier¶
수정자 포함 참조
Snowflake는 여러 개의 CTEs
(공통 테이블 식)이 있는 SELECT 문에서 Teradata의 WITH
수정자를 지원합니다. Teradata는 CTE 정의가 선언되기 전에 참조되는지 여부에 관계없이 모든 순서를 지원하지만, Snowflake는 CTE 가 다른 CTE 를 호출하는 경우 반드시 그 전에 정의할 것을 요구합니다. 그런 다음 WITH 내에서 변환된 CTEs 시퀀스는 참조되지 않은 CTEs, 다음 CTE 를 호출하는 CTE 로 순서가 재지정됩니다.
WITH 호출 시퀀스에서 사이클이 감지된 경우, SSC-EWI-TD0077 의 예제에 설명된 대로 시퀀스를 변경하지 않고 원본 그대로 유지합니다. 아래 예에서는 n1과 n2라는 이름의 CTEs 가 2개 있으며, n1은 n2를 참조합니다. 그런 다음 n2를 해당 변환된 코드로 Snowflake에서 먼저 정의해야 합니다.
참고
출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.
Teradata
WITH recursive n1(c1) as (select c1, c3 from t2, n1),
n2(c2) as (select c2 from tablex)
SELECT * FROM t1;
Snowflake
WITH RECURSIVE n1(c1) AS
(
SELECT
c1,
c3 from
t2, n1
),
n2(c2) AS
(
SELECT
c2 from
tablex
)
SELECT
* FROM
t1;
Known Issues¶
1. Impossible to reorder when cycles were found¶
CTEs 참조가 분석되고 CTEs 호출 사이에 주기가 있는 경우 CTEs 는 주문되지 않습니다.
관련 EWIs¶
관련 EWIs 없음.
Insert 문¶
참고
출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.
Insert 문 참조
Teradata에는 각 테이블 열의 값을 인라인으로 할당하는 대체 INSERT
구문이 있습니다. 이 대체 구조를 사용하려면 Snowflake에서 지원되는 특수 변환이 필요합니다. 값의 인라인 할당은 분리되어 Snowflake INSERT INTO
문의 VALUES(...)
부분 내에 배치됩니다.
Teradata
INSERT INTO appDB.logTable (
process_name = 'S2F_BOOKS_LOAD_NEW'
, session_id = 105678989
, message_txt = ''
, message_ts = '2019-07-23 00:00:00'
, Insert_dt = CAST((CURRENT_TIMESTAMP(0)) AS DATE FORMAT 'YYYY-MM-DD'));
Snowflake
INSERT INTO appDB.logTable (
process_name, session_id, message_txt, message_ts, Insert_dt)
VALUES ('S2F_BOOKS_LOAD_NEW', 105678989, '', '2019-07-23 00:00:00', TO_DATE((CURRENT_TIMESTAMP(0))));
알려진 문제 ¶
문제가 발견되지 않았습니다.
관련 EWIs ¶
관련 EWIs 없음.
LOGGING ERRORS¶
참고
출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.
참고
관련 없는 문.
경고
이 문은 관련 없는 구문이므로 마이그레이션 에서 제거되었습니다. 즉, Snowflake에서는 필수가 아닙니다.
설명¶
문을 INSERT ... SELECT 로 사용할 때 오류를 로그에 기록하는 문입니다.
다음 설명서 를 참조하십시오.
샘플 소스 패턴¶
LOGGING ERRORS¶
이 예제에서는 LOGGING ERRORS
가 관련 구문이 아니므로 제거되었습니다. 이 구문은 Snowflake에서 필수가 아닙니다.
INSERT INTO MY_TABLE
SELECT *
FROM MY_SAMPLE
LOGGING ERRORS;
INSERT INTO MY_TABLE SELECT
*
FROM
MY_SAMPLE;
LOGGING ALL ERRORS¶
이 예제에서는 LOGGING ALL ERRORS
가 관련 구문이 아니므로 제거되었음을 알 수 있습니다. 이 구문은 Snowflake에서 필수가 아닙니다.
INSERT INTO MY_TABLE
SELECT *
FROM MY_SAMPLE
LOGGING ALL ERRORS;
INSERT INTO MY_TABLE SELECT
*
FROM
MY_SAMPLE;
LOGGING ERRORS WITH NO LIMIT¶
이 예제에서는 LOGGING ERRORS WITH NO LIMIT
가 관련 구문이 아니므로 제거되었음을 알 수 있습니다. 이 구문은 Snowflake에서 필수가 아닙니다.
INSERT INTO MY_TABLE
SELECT *
FROM MY_SAMPLE
LOGGING ERRORS WITH NO LIMIT;
INSERT INTO MY_TABLE SELECT
*
FROM
MY_SAMPLE;
LOGGING ERRORS WITH LIMIT OF¶
이 예제에서는 LOGGING ERRORS WITH LIMIT OF
가 관련 구문이 아니므로 제거되었음을 알 수 있습니다. 이 구문은 Snowflake에서 필수가 아닙니다.
INSERT INTO MY_TABLE
SELECT *
FROM MY_SAMPLE
LOGGING ERRORS WITH LIMIT OF 100;
INSERT INTO MY_TABLE SELECT
*
FROM
MY_SAMPLE;
알려진 문제 ¶
문제가 발견되지 않았습니다.
관련 EWIs ¶
관련 EWIs 없음.
Select 문¶
Select 문 참조
Snowflake는 몇 가지 예외를 제외하고 Teradata의 SELECT
구문을 지원합니다. 기본적으로 SEL
약어는 지원하지 않습니다.
Teradata
SEL DISTINCT col1, col2 FROM table1
Snowflake
SELECT DISTINCT col1,
col2 FROM
table1;
Teradata는 별칭을 선언하기 전에 참조하는 기능을 지원하지만, Snowflake는 지원하지 않습니다. 이 시나리오의 변환은 참조된 열을 가져와서 참조하는 열 이름의 별칭을 변경하는 것입니다.
Teradata
SELECT
my_val, sum(col1),
col2 AS my_val FROM table1
Snowflake
SELECT
my_val,
sum(col1),
col2 AS my_val FROM
table1;
제거된 절 옵션¶
다음 절 옵션은 Snowflake와 관련이 없으므로 마이그레이션 중에 제거됩니다.
Teradata |
Snowflake |
---|---|
Expand on |
지원 안 됨 |
Normalize |
지원 안 됨 |
With check option (Query) |
지원 안 됨 |
Known Issues¶
1. SEL abbreviation unsupported¶
이 약어는 Snowflake에서 지원되지 않지만, SELECT 로 변경하면 올바르게 변환됩니다.
관련 EWIs¶
관련 EWIs 없음.
ANY 조건자¶
경고
이는 현재 진행 중인 작업으로 향후 변경 사항이 적용될 수 있습니다.
설명¶
Teradata에서는 비교 작업 또는 IN/NOT IN 조건자에서 정량화가 가능합니다. 식과 하위 쿼리에서 반환된 값 세트의 1개 이상의 값을 비교하면 true입니다. 자세한 내용은 다음 Teradata 설명서 를 검토하십시오.
Teradata 구문
{ expression quantifier ( literal [ {, | OR} ... ] ) |
{ expression | ( expression [,...] ) } quantifier ( subquery )
}
여기서 한정자:
{ comparison_operator [ NOT ] IN } { ALL |ANY | SOME }
Snowflake 구문
하위 쿼리 형식에서 IN 은 = ANY
와 같고 NOT IN 은 <>ALL
과 같습니다. 자세한 내용은 다음 Snowflake 설명서 를 참조하십시오.
개별 값을 비교하려면:
<value> [ NOT ] IN ( <value_1> [ , <value_2> ... ] )
row constructors(괄호로 묶인 값 목록)를 비교하려면:
( <value_A> [, <value_B> ... ] ) [ NOT ] IN ( ( <value_1> [ , <value_2> ... ] ) [ , ( <value_3> [ , <value_4> ... ] ) ... ] )
값을 하위 쿼리에서 반환된 값과 비교하려면:
<value> [ NOT ] IN ( <subquery> )
Sample Source Patterns
샘플 데이터
Teradata
CREATE TABLE Employee (
EmpNo INT,
Name VARCHAR(100),
DeptNo INT
);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (1, 'Alice', 100);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (2, 'Bob', 300);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (3, 'Charlie', 500);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (4, 'David', 200);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (5, 'Eve', 100);
Snowflake
CREATE OR REPLACE TABLE Employee (
EmpNo INT,
Name VARCHAR(100),
DeptNo INT
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "teradata", "convertedOn": "01/14/2025", "domain": "test" }}'
;
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (1, 'Alice', 100);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (2, 'Bob', 300);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (3, 'Charlie', 500);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (4, 'David', 200);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (5, 'Eve', 100);
WHERE 절에서 ANY 술어와 같음
Teradata
SELECT DeptNo
FROM Employee
WHERE DeptNo = ANY(100,300,500) ;
DeptNo |
---|
100 |
500 |
100 |
300 |
Snowflake
SELECT DeptNo
FROM Employee
WHERE DeptNo IN(100,300,500) ;
DeptNo |
---|
100 |
500 |
100 |
300 |
WHERE 절의 기타 비교 연산자
다른 비교 연산자가 있는 경우 필수 하위 쿼리를 추가하는 것이 이에 상응하는 변환입니다.
Teradata
SELECT Name, DeptNo
FROM Employee
WHERE DeptNo < ANY(100,300,500) ;
이름 |
DeptNo |
---|---|
Eve |
100 |
Alice |
100 |
David |
200 |
Bob |
300 |
Snowflake
SELECT Name, DeptNo
FROM Employee
WHERE DeptNo < ANY
(SELECT DeptNo
FROM Employee
WHERE DeptNo > 100
OR DeptNo > 300
OR DeptNo > 500);
NAME |
DEPTNO |
---|---|
Alice |
100 |
Eve |
100 |
Bob |
300 |
David |
200 |
WHERE 절의 IN ANY
Teradata
SELECT DeptNo
FROM Employee
WHERE DeptNo IN ANY(100,300,500) ;
DeptNo |
---|
100 |
500 |
100 |
300 |
Snowflake
SELECT DeptNo
FROM Employee
WHERE DeptNo IN(100,300,500) ;
DeptNo |
---|
100 |
500 |
100 |
300 |
WHERE 절의 NOT IN ALL
Teradata
SELECT Name, DeptNo
FROM Employee
WHERE DeptNo NOT IN ALL(100, 200);
이름 |
DeptNo |
---|---|
Charlie |
500 |
Bob |
300 |
Snowflake
SELECT Name, DeptNo
FROM Employee
WHERE DeptNo NOT IN (100, 200);
이름 |
DeptNo |
---|---|
Charlie |
500 |
Bob |
300 |
Known Issues
WHERE 절의 NOT IN ANY
Teradata
SELECT Name, DeptNo
FROM Employee
WHERE DeptNo NOT IN ANY(100, 200);
이름 |
DeptNo |
---|---|
Eve |
100 |
Charlie |
500 |
Alice |
100 |
David |
200 |
Bob |
300 |
Snowflake
SELECT Name, DeptNo
FROM Employee
WHERE DeptNo IN (100, 200)
OR DeptNo NOT IN (100, 200);
이름 |
DeptNo |
---|---|
Eve |
100 |
Charlie |
500 |
Alice |
100 |
David |
200 |
Bob |
300 |
Related EWIs
관련 EWIs 없음.
Expand On 절
Description
Expand On 절은 기간 데이터 타입을 가진 열을 확장하여 입력 행의 기간 값을 기반으로 일반 시계열 행을 생성합니다. Expand On 절에 대한 자세한 내용은 Teradata 설명서 를 참조하십시오.
Sample Source Patterns
참고
출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.
샘플 데이터¶
CREATE TABLE table1 (id INTEGER, pd PERIOD (TIMESTAMP));
INSERT INTO
table1
VALUES
(
1,
PERIOD(
TIMESTAMP '2022-05-23 10:15:20.00009',
TIMESTAMP '2022-05-23 10:15:25.000012'
)
);
CREATE OR REPLACE TABLE table1 (
id INTEGER,
pd VARCHAR(58) !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"teradata"}}'
;
INSERT INTO table1
VALUES (
1, PUBLIC.PERIOD_UDF(
TIMESTAMP '2022-05-23 10:15:20.00009',
TIMESTAMP '2022-05-23 10:15:25.000012'
) !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!);
Expand On 절¶
기간 열을 초 단위로 확장하고 싶다고 가정해 보겠습니다. 이 확장 절에는 앵커 기간 확장 및 간격 리터럴 확장이 있습니다.
앵커 기간 확장
SELECT
id,
BEGIN(bg)
FROM
table1 EXPAND ON pd AS bg BY ANCHOR ANCHOR_SECOND;
id |
BEGIN (bg) |
---|---|
1 |
2022-05-23 10:15:21.0000 |
1 |
2022-05-23 10:15:22.0000 |
1 |
2022-05-23 10:15:23.0000 |
1 |
2022-05-23 10:15:24.0000 |
1 |
2022-05-23 10:15:25.0000 |
Snowflake는 Expand On을 지원하지 않습니다. 동일한 결과와 기능을 재현하기 위해 Teradata SQL 코드는 CTE 블록에 포함되며, EXPAND_ON_UDF 및 TABLE 함수를 사용하여 여러 행을 반환하는 FLATTEN 함수, ROW_COUNT_UDF 및 DIFF_TTIME_PERIOD_UDF 를 사용하여 필요한 행 수를 표시하고 VALUE 를 반환하여 EXPAND_ON_UDF 가 다른 정규 시계열을 계산할 수 있도록 도와줍니다. 이 CTE 블록은 Expand On 절에서와 동일한 확장 열 별칭을 반환하므로 모든 기간 데이터 타입 사용에서 결과를 사용할 수 있습니다.
WITH ExpandOnCTE AS
(
SELECT
PUBLIC.EXPAND_ON_UDF('ANCHOR_SECOND', VALUE, pd) bg
FROM
table1,
TABLE(FLATTEN(PUBLIC.ROW_COUNT_UDF(PUBLIC.DIFF_TIME_PERIOD_UDF('ANCHOR_SECOND', pd))))
)
SELECT
id,
PUBLIC.PERIOD_BEGIN_UDF(bg) !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!
FROM
table1,
ExpandOnCTE;
id |
PERIOD_BEGIN_UDF(bg) |
---|---|
1 |
2022-05-23 10:15:21.0000 |
1 |
2022-05-23 10:15:22.0000 |
1 |
2022-05-23 10:15:23.0000 |
1 |
2022-05-23 10:15:24.0000 |
1 |
2022-05-23 10:15:25.0000 |
Known Issues¶
Expand On 절은 간격 리터럴 확장을 사용할 수 있으며, 이 경우 SnowConvert 는 이 변환이 계획되어 있음을 나타내는 오류를 추가합니다.
간격 리터럴 확장¶
SELECT
id,
BEGIN(bg)
FROM
table1 EXPAND ON pd AS bg BY INTERVAL '1' SECOND;
id |
BEGIN (bg) |
---|---|
1 |
2022-05-23 10:15:20.0000 |
1 |
2022-05-23 10:15:21.0000 |
1 |
2022-05-23 10:15:22.0000 |
1 |
2022-05-23 10:15:23.0000 |
1 |
2022-05-23 10:15:24.0000 |
SELECT
id,
PUBLIC.PERIOD_BEGIN_UDF(bg) !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!
FROM
table1
!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'EXPAND ON' NODE ***/!!!
EXPAND ON pd AS bg BY INTERVAL '1' SECOND;
관련 EWIs¶
SSC-EWI-0073: 보류 중 함수 동등성 검토.
SSC-EWI-TD0053: Snowflake는 기간 데이터 타입을 지원하지 않으며, 모든 기간은 대신 varchar로 처리됩니다.
Normalize¶
설명¶
NORMALIZE 는 첫 번째 기간 열의 기간 값이 서로 일치하거나 겹치는 경우 결합하여 개별 기간 값을 포괄하는 기간을 형성하도록 지정합니다. 정규화 절에 대한 자세한 내용은 Teradata 설명서 를 참조하십시오.
샘플 소스 패턴¶
참고
출력 코드의 일부 부분은 명확성을 위해 생략되었습니다.
샘플 데이터¶
CREATE TABLE project (
emp_id INTEGER,
project_name VARCHAR(20),
dept_id INTEGER,
duration PERIOD(DATE)
);
INSERT INTO project
VALUES
(
10,
'First Phase',
1000,
PERIOD(DATE '2010-01-10', DATE '2010-03-20')
);
INSERT INTO project
VALUES
(
10,
'First Phase',
2000,
PERIOD(DATE '2010-03-20', DATE '2010-07-15')
);
INSERT INTO project
VALUES
(
10,
'Second Phase',
2000,
PERIOD(DATE '2010-06-15', DATE '2010-08-18')
);
INSERT INTO project
VALUES
(
20,
'First Phase',
2000,
PERIOD(DATE '2010-03-10', DATE '2010-07-20')
);
INSERT INTO project
VALUES
(
20,
'Second Phase',
1000,
PERIOD(DATE '2020-05-10', DATE '2020-09-20')
);
CREATE OR REPLACE TABLE project (
emp_id INTEGER,
project_name VARCHAR(20),
dept_id INTEGER,
duration VARCHAR(24) !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"teradata"}}'
;
INSERT INTO project
VALUES (
10,
'First Phase',
1000, PUBLIC.PERIOD_UDF(DATE '2010-01-10', DATE '2010-03-20') !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!);
INSERT INTO project
VALUES (
10,
'First Phase',
2000, PUBLIC.PERIOD_UDF(DATE '2010-03-20', DATE '2010-07-15') !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!);
INSERT INTO project
VALUES (
10,
'Second Phase',
2000, PUBLIC.PERIOD_UDF(DATE '2010-06-15', DATE '2010-08-18') !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!);
INSERT INTO project
VALUES (
20,
'First Phase',
2000, PUBLIC.PERIOD_UDF(DATE '2010-03-10', DATE '2010-07-20') !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!);
INSERT INTO project
VALUES (
20,
'Second Phase',
1000, PUBLIC.PERIOD_UDF(DATE '2020-05-10', DATE '2020-09-20') !!!RESOLVE EWI!!! /*** SSC-EWI-TD0053 - SNOWFLAKE DOES NOT SUPPORT THE PERIOD DATATYPE, ALL PERIODS ARE HANDLED AS VARCHAR INSTEAD ***/!!!);
정규화 절¶
직원 ID와 함께 정규화 절을 사용한다고 가정해 보겠습니다.
SELECT
NORMALIZE emp_id,
duration
FROM
project;
EMP_ID |
DURATION |
---|---|
20 |
(2010-03-10, 2010-07-20) |
10 |
(2010-01-10, 2010-08-18) |
20 |
(2020-05-10, 2010-09-20) |
!!!RESOLVE EWI!!! /*** SSC-EWI-TD0079 - THE REQUIRED PERIOD TYPE COLUMN WAS NOT FOUND ***/!!!
WITH NormalizeCTE AS
(
SELECT
T1.*,
SUM(GroupStartFlag)
OVER (
PARTITION BY
emp_id, duration
ORDER BY
PeriodColumn_begin
ROWS UNBOUNDED PRECEDING) GroupID
FROM
(
SELECT
emp_id,
duration,
PUBLIC.PERIOD_BEGIN_UDF(PeriodColumn) PeriodColumn_begin,
PUBLIC.PERIOD_END_UDF(PeriodColumn) PeriodColumn_end,
(CASE
WHEN PeriodColumn_begin <= LAG(PeriodColumn_end)
OVER (
PARTITION BY
emp_id, duration
ORDER BY
PeriodColumn_begin,
PeriodColumn_end)
THEN 0
ELSE 1
END) GroupStartFlag
FROM
project
) T1
)
SELECT
emp_id,
duration,
PUBLIC.PERIOD_UDF(MIN(PeriodColumn_begin), MAX(PeriodColumn_end))
FROM
NormalizeCTE
GROUP BY
emp_id,
duration,
GroupID;
EMP_ID |
PUBLIC.PERIOD_UDF(MIN(START_DATE), MAX(END_DATE)) |
---|---|
20 |
2020-05-10*2010-09-20 |
20 |
2010-03-10*2010-07-20 |
10 |
2010-01-10*2010-08-18 |
Known Issues¶
Normalize 절은 이러한 경우에 ON MEETS OR OVERLAPS, ON OVERLAPS 또는 ON OVERLAPS OR MEETS, 를 사용할 수 있습니다. SnowConvert 는 이 변환이 향후 계획되어 있음을 나타내는 오류를 추가합니다.
SELECT NORMALIZE ON MEETS OR OVERLAPS emp_id, duration FROM table1;
SELECT
!!!RESOLVE EWI!!! /*** SSC-EWI-0073 - PENDING FUNCTIONAL EQUIVALENCE REVIEW FOR 'NORMALIZE SET QUANTIFIER' NODE ***/!!!
NORMALIZE ON MEETS OR OVERLAPS emp_id,
duration FROM
table1;
관련 EWIs¶
SSC-EWI-0073: 보류 중 함수 동등성 검토.
SSC-EWI-TD0079: 필수 기간 유형 열을 찾을 수 없습니다.
SSC-EWI-TD0053: Snowflake는 기간 데이터 타입을 지원하지 않으며, 모든 기간은 대신 varchar로 처리됩니다.
재설정 시기¶
설명¶
재설정 시 특정 조건에 따라 SQL 윈도우 함수가 작업할 파티션을 결정합니다. 조건이 true로 평가되면 기존 윈도우 파티션 내에 새 동적 하위 파티션이 생성됩니다. 재설정 시점에 대한 자세한 내용은 Teradata 설명서를 참조하십시오.
샘플 소스 패턴¶
샘플 데이터¶
Teradata
CREATE TABLE account_balance
(
account_id INTEGER NOT NULL,
month_id INTEGER,
balance INTEGER
)
UNIQUE PRIMARY INDEX (account_id, month_id);
INSERT INTO account_balance VALUES (1, 1, 60);
INSERT INTO account_balance VALUES (1, 2, 99);
INSERT INTO account_balance VALUES (1, 3, 94);
INSERT INTO account_balance VALUES (1, 4, 90);
INSERT INTO account_balance VALUES (1, 5, 80);
INSERT INTO account_balance VALUES (1, 6, 88);
INSERT INTO account_balance VALUES (1, 7, 90);
INSERT INTO account_balance VALUES (1, 8, 92);
INSERT INTO account_balance VALUES (1, 9, 10);
INSERT INTO account_balance VALUES (1, 10, 60);
INSERT INTO account_balance VALUES (1, 11, 80);
INSERT INTO account_balance VALUES (1, 12, 10);
account_id |
month_id |
balance |
---|---|---|
1 |
1 |
60 |
1 |
2 |
99 |
1 |
3 |
94 |
1 |
4 |
90 |
1 |
5 |
80 |
1 |
6 |
88 |
1 |
7 |
90 |
1 |
8 |
92 |
1 |
9 |
10 |
1 |
10 |
60 |
1 |
11 |
80 |
1 |
12 |
10 |
Snowflake
CREATE OR REPLACE TABLE account_balance (
account_id INTEGER NOT NULL,
month_id INTEGER,
balance INTEGER,
UNIQUE (account_id, month_id)
)
COMMENT = '{"origin":"sf_sc","name":"snowconvert","version":{"major":1, "minor":0},{"attributes":{"component":"teradata"}}'
;
INSERT INTO account_balance
VALUES (1, 1, 60);
INSERT INTO account_balance
VALUES (1, 2, 99);
INSERT INTO account_balance
VALUES (1, 3, 94);
INSERT INTO account_balance
VALUES (1, 4, 90);
INSERT INTO account_balance
VALUES (1, 5, 80);
INSERT INTO account_balance
VALUES (1, 6, 88);
INSERT INTO account_balance
VALUES (1, 7, 90);
INSERT INTO account_balance
VALUES (1, 8, 92);
INSERT INTO account_balance
VALUES (1, 9, 10);
INSERT INTO account_balance
VALUES (1, 10, 60);
INSERT INTO account_balance
VALUES (1, 11, 80);
INSERT INTO account_balance
VALUES (1, 12, 10);
account_id |
month_id |
balance |
---|---|---|
1 |
1 |
60 |
1 |
2 |
99 |
1 |
3 |
94 |
1 |
4 |
90 |
1 |
5 |
80 |
1 |
6 |
88 |
1 |
7 |
90 |
1 |
8 |
92 |
1 |
9 |
10 |
1 |
10 |
60 |
1 |
11 |
80 |
1 |
12 |
10 |
재설정 시기¶
각 계정에 대해 연속적인 월별 잔액 증가 시퀀스를 분석하고 싶다고 가정해 보겠습니다. 한 달 잔액이 전월 잔액보다 적거나 같으면 카운터를 0으로 재설정하고 다시 시작해야 한다는 요구 사항이 있습니다.
이 데이터를 분석하기 위해 Teradata SQL 은 다음과 같이 중첩 집계 및 Reset When 문이 포함된 윈도우 함수를 사용합니다.
Teradata¶
SELECT
account_id,
month_id,
balance,
(
ROW_NUMBER() OVER (
PARTITION BY account_id
ORDER BY
month_id RESET WHEN balance <= SUM(balance) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
)
) -1
) AS balance_increase
FROM account_balance
ORDER BY 1, 2;
account_id | month_id | balance | balance_increase |
---|---|---|---|
1 | 1 | 60 | 0 |
1 | 2 | 99 | 1 |
1 | 3 | 94 | 0 |
1 | 4 | 90 | 0 |
1 | 5 | 80 | 0 |
1 | 6 | 88 | 1 |
1 | 7 | 90 | 2 |
1 | 8 | 92 | 3 |
1 | 9 | 10 | 0 |
1 | 10 | 60 | 1 |
1 | 11 | 80 | 2 |
1 | 12 | 10 | 0 |
Snowflake
Snowflake는 윈도우 함수에서 Reset When 절을 지원하지 않습니다. 동일한 결과를 재현하려면 다음과 같이 기본 SQL 구문과 중첩된 하위 쿼리를 사용하여 Teradata SQL 코드를 변환해야 합니다.
SELECT
account_id,
month_id,
balance,
(
ROW_NUMBER() OVER (
PARTITION BY
account_id, new_dynamic_part
ORDER BY
month_id
) -1
) AS balance_increase
FROM
(
SELECT
account_id,
month_id,
balance,
previous_value,
SUM(dynamic_part) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS new_dynamic_part
FROM
(
SELECT
account_id,
month_id,
balance,
SUM(balance) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
) AS previous_value,
(CASE
WHEN balance <= previous_value
THEN 1
ELSE 0
END) AS dynamic_part
FROM
account_balance
)
)
ORDER BY 1, 2;
account_id | month_id | balance | balance_increase |
---|---|---|---|
1 | 1 | 60 | 0 |
1 | 2 | 99 | 1 |
1 | 3 | 94 | 0 |
1 | 4 | 90 | 0 |
1 | 5 | 80 | 0 |
1 | 6 | 88 | 1 |
1 | 7 | 90 | 2 |
1 | 8 | 92 | 3 |
1 | 9 | 10 | 0 |
1 | 10 | 60 | 1 |
1 | 11 | 80 | 2 |
1 | 12 | 10 | 0 |
Snowflake에서 언제 재설정 기능을 지원하려면 2개의 중첩된 하위 쿼리가 필요합니다.
내부 하위 쿼리에서 동적 파티션 표시기(dynamic_part)가 생성되어 채워집니다. 한 달의 잔액이 전월 잔액보다 작거나 같으면 dynamic_part가 1로 설정되고, 그렇지 않으면 0으로 설정됩니다.
다음 레이어에서는 SUM 윈도우 함수의 결과로 new_dynamic_part 특성이 생성됩니다.
마지막으로, 기존 파티션 특성(account_id)에 새 파티션 특성(동적 파티션)으로 new_dynamic_part를 추가하고 Teradata에서와 동일한 ROW_NUMBER() 윈도우 함수를 적용합니다.
이러한 변경 후 Snowflake는 Teradata와 동일한 출력을 생성합니다.
조건부 윈도우 함수가 열인 경우 재설정하기¶
위와 동일한 예제이지만, 이제 RESET WHEN 조건에 사용된 윈도우 함수가 previous
라는 열로 정의된다는 점을 예외로 합니다. 이 변형에서는 이전 예제에서와 같이 previous_value
를 정의할 필요가 없으므로 변환이 약간 변경됩니다. 동일한 해결 방법입니다.
Teradata
SELECT
account_id,
month_id,
balance,
SUM(balance) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
) AS previous,
(
ROW_NUMBER() OVER (
PARTITION BY account_id
ORDER BY
month_id RESET WHEN balance <= previous
)
) AS balance_increase
FROM account_balance
ORDER BY 1, 2;
account_id | month_id | balance | previous | balance_increase |
---|---|---|---|---|
1 | 1 | 60 | 0 | |
1 | 2 | 99 | 60 | 1 |
1 | 3 | 94 | 99 | 0 |
1 | 4 | 90 | 94 | 0 |
1 | 5 | 80 | 90 | 0 |
1 | 6 | 88 | 80 | 1 |
1 | 7 | 90 | 88 | 2 |
1 | 8 | 92 | 90 | 3 |
1 | 9 | 10 | 92 | 0 |
1 | 10 | 60 | 10 | 1 |
1 | 11 | 80 | 60 | 2 |
1 | 12 | 10 | 80 | 0 |
Snowflake
SELECT
account_id,
month_id,
balance,
SUM(balance) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
) AS previous,
(
ROW_NUMBER() OVER (
PARTITION BY
account_id, new_dynamic_part
ORDER BY
month_id
)
) AS balance_increase
FROM
(
SELECT
account_id,
month_id,
balance,
SUM(balance) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
) AS previous,
SUM(dynamic_part) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
) AS new_dynamic_part
FROM
(
SELECT
account_id,
month_id,
balance,
SUM(balance) OVER (
PARTITION BY account_id
ORDER BY month_id
ROWS BETWEEN 1 PRECEDING AND 1 PRECEDING
) AS previous,
(CASE
WHEN balance <= previous
THEN 1
ELSE 0
END) AS dynamic_part
FROM
account_balance
)
)
ORDER BY 1, 2;
account_id | month_id | balance | previous | balance_increase |
---|---|---|---|---|
1 | 1 | 60 | 0 | |
1 | 2 | 99 | 60 | 1 |
1 | 3 | 94 | 99 | 0 |
1 | 4 | 90 | 94 | 0 |
1 | 5 | 80 | 90 | 0 |
1 | 6 | 88 | 80 | 1 |
1 | 7 | 90 | 88 | 2 |
1 | 8 | 92 | 90 | 3 |
1 | 9 | 10 | 92 | 0 |
1 | 10 | 60 | 10 | 1 |
1 | 11 | 80 | 60 | 2 |
1 | 12 | 10 | 80 | 0 |
Known Issues¶
RESET WHEN 절은 조건에 따라 일부 변형이 있을 수 있습니다. 현재 SnowConvert 는 이진 조건(<=, >=, <> 또는 =)만 지원합니다. IS NOT NULL
과 같은 다른 유형의 경우 이는 Snowflake에서 지원되지 않기 때문에 SnowConvert 는 RESET WHEN 절을 제거하고 오류 메시지를 추가합니다. 다음 예제를 참조하십시오.
Teradata¶
SELECT
account_id,
month_id,
balance,
ROW_NUMBER() OVER (
PARTITION BY account_id
ORDER BY month_id
RESET WHEN balance IS NOT NULL
ROWS UNBOUNDED PRECEDING
) as balance_increase
FROM account_balance
ORDER BY 1,2;
Snowflake
SELECT
account_id,
month_id,
balance,
ROW_NUMBER() OVER (
PARTITION BY account_id
!!!RESOLVE EWI!!! /*** SSC-EWI-TD0077 - RESET WHEN CLAUSE IS NOT SUPPORTED IN THIS SCENARIO DUE TO ITS CONDITION ***/!!!
ORDER BY month_id
ROWS UNBOUNDED PRECEDING
) as balance_increase
FROM
account_balance
ORDER BY 1,2;
관련 EWIs¶
SSC-EWI-TD0077: 조건으로 인해 이 시나리오에서는 RESET WHEN 절이 지원되지 않습니다.
SAMPLE 절¶
설명¶
Teradata의 SAMPLE 절은 처리할 행 수를 줄이며 1개 이상의 행 샘플을 분수 목록 또는 행 수 목록으로 반환합니다. 이 절은 SELECT 쿼리에서 사용됩니다. 자세한 내용은 다음 Teradata 설명서 를 검토하십시오.
Teradata 구문
SAMPLE
[ WITH REPLACEMENT ]
[ RANDOMIZED LOCALIZATION ]
{ { fraction_description | count_description } [,...] |
when_clause ]
}
Snowflake 구문
자세한 내용은 다음 Snowflake 설명서 를 참조하십시오. SAMPLE
및 TABLESAMPLE
은 동의어입니다.
SELECT ...
FROM ...
{ SAMPLE | TABLESAMPLE } [ samplingMethod ]
[ ... ]
여기서
samplingMethod ::= {
{ BERNOULLI | ROW } ( { <probability> | <num> ROWS } ) |
{ SYSTEM | BLOCK } ( <probability> ) [ { REPEATABLE | SEED } ( <seed> ) ] }
Snowflake에서는 다음 키워드를 서로 바꿔서 사용할 수 있습니다.
SAMPLE | TABLESAMPLE
BERNOULLI | ROW
SYSTEM | BLOCK
REPEATABLE | SEED
다음 테이블을 검토하여 주요 차이점을 확인하십시오.
SAMPLE 동작 |
Teradata |
Snowflake |
---|---|---|
확률별 샘플 |
분수 설명이라고도 합니다. 0,1에서 1 사이의 소수점이어야 합니다. |
0에서 100 사이의 소수점 숫자입니다. |
수정된 행 수 |
카운트 설명이라고도 합니다. 샘플링할 행의 수를 결정하는 양의 정수입니다. |
테이블에서 샘플을 추출할 행 수(최대 1,000,000개)를 지정합니다. |
반복 행 |
|
|
샘플링 방법 |
Proportional 및 |
|
샘플 소스 패턴¶
샘플 데이터¶
Teradata
CREATE TABLE Employee (
EmpNo INT,
Name VARCHAR(100),
DeptNo INT
);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (1, 'Alice', 100);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (2, 'Bob', 300);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (3, 'Charlie', 500);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (4, 'David', 200);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (5, 'Eve', 100);
Snowflake
CREATE OR REPLACE TABLE Employee (
EmpNo INT,
Name VARCHAR(100),
DeptNo INT
)
COMMENT = '{ "origin": "sf_sc", "name": "snowconvert", "version": { "major": 0, "minor": 0, "patch": "0" }, "attributes": { "component": "teradata", "convertedOn": "01/14/2025", "domain": "test" }}'
;
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (1, 'Alice', 100);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (2, 'Bob', 300);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (3, 'Charlie', 500);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (4, 'David', 200);
INSERT INTO Employee (EmpNo, Name, DeptNo)
VALUES (5, 'Eve', 100);
SAMPLE 절¶
수정된 행 수
이 예제에서 행 수는 수정된 수이지만 각 실행마다 반드시 동일한 결과가 나오는 것은 아닙니다.
Teradata
SELECT * FROM Employee SAMPLE 2;
2개 행.
Snowflake
SELECT * FROM Employee SAMPLE (2 ROWS);
2개 행.
확률에 따른 행 번호
이 옵션은 설정된 확률에 따라 다양한 행을 반환합니다.
Teradata
SELECT * FROM Employee SAMPLE 0.25;
각 행에 대해 25%의 확률: 출력 행 1개.
Snowflake
SELECT * FROM Employee SAMPLE (25);
각 행에 대해 25%의 확률: 출력 행 1개.
Known Issues¶
교체가 가능한 행 수 수정¶
이 옵션은 수정된 수의 행을 반환하며 행을 반복할 수 있습니다. Snowflake에서는 테이블의 행 수보다 많은 샘플을 요청할 수 없습니다.
Teradata 샘플
SELECT * FROM Employee SAMPLE WITH REPLACEMENT 8;
EmpNo |
이름 |
DeptNo |
---|---|---|
5 |
Eve |
100 |
5 |
Eve |
100 |
5 |
Eve |
100 |
4 |
David |
200 |
4 |
David |
200 |
3 |
Charlie |
500 |
1 |
Alice |
100 |
1 |
Alice |
100 |