如何在 Teradata 中编写动态 SQL 代码?
How to write a dynamic SQL code in Teradata?
我正在尝试转换此代码(它接受列名作为输入,对输入列进行计算并将数据插入 table)。现在我知道我们不能通过存储过程或宏传递 table/column 名称,我开始知道我们可以通过动态 SQL 来传递它。我不确定语法应该如何,因为我找不到一个清晰简单的例子。下面是我需要转换的代码:
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
SELECT
'DURATION_CELL_CURR' AS COLMN,
PW_END_DATE,
'ACPT' AS TAB,
MIN(DURATION_CELL_CURR) AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN DURATION_CELL_CURR END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN DURATION_CELL_CURR END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN DURATION_CELL_CURR END) AS PER_75,
MAX(DURATION_CELL_CURR) AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY DURATION_CELL_CURR) AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)A
GROUP BY 1,2,3
UNION ALL
SELECT
'DURATION_CELL_CURR' AS COLMN,
PW_END_DATE,
'PROD' AS TAB,
MIN(DURATION_CELL_CURR) AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN DURATION_CELL_CURR END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN DURATION_CELL_CURR END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN DURATION_CELL_CURR END) AS PER_75,
MAX(DURATION_CELL_CURR) AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY DURATION_CELL_CURR) AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)B
GROUP BY 1,2,3
下面是我对其动态转换的理解SQL:
REPLACE PROCEDURE PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE (IN COL CHAR(50))
(
BEGIN REQUEST
CALL DBC.SYSEXECSQL
('
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''ACPT'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)A
GROUP BY 1,2,3
UNION ALL
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''PROD'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)B
GROUP BY 1,2,3
')
END REQUEST;
);
我知道在 运行-ready 之前我必须解决许多错误。所以我遇到的第一个错误如下:
谁能帮我解决这个问题。我必须计算 60 多个这样的列的分位数分布,手动操作是疯狂的。
非常感激。
皮尤什
应该删除 BEGIN
之前的一对括号,并且包括日期在内的所有字符串周围的单引号都必须加倍:
REPLACE PROCEDURE NPVAZ_CVM_CHECK_TEST_CASE (IN COL CHAR(50))
BEGIN
CALL DBC.SYSEXECSQL
('
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''ACPT'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
WHERE PC.PW_END_DATE = DATE ''2017-01-17''
)A
GROUP BY 1,2,3
UNION ALL
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''PROD'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.PROD_CVM PC
WHERE PC.PW_END_DATE = DATE ''2017-01-17''
)B
GROUP BY 1,2,3
');
END;
我正在尝试转换此代码(它接受列名作为输入,对输入列进行计算并将数据插入 table)。现在我知道我们不能通过存储过程或宏传递 table/column 名称,我开始知道我们可以通过动态 SQL 来传递它。我不确定语法应该如何,因为我找不到一个清晰简单的例子。下面是我需要转换的代码:
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
SELECT
'DURATION_CELL_CURR' AS COLMN,
PW_END_DATE,
'ACPT' AS TAB,
MIN(DURATION_CELL_CURR) AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN DURATION_CELL_CURR END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN DURATION_CELL_CURR END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN DURATION_CELL_CURR END) AS PER_75,
MAX(DURATION_CELL_CURR) AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY DURATION_CELL_CURR) AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)A
GROUP BY 1,2,3
UNION ALL
SELECT
'DURATION_CELL_CURR' AS COLMN,
PW_END_DATE,
'PROD' AS TAB,
MIN(DURATION_CELL_CURR) AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN DURATION_CELL_CURR END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN DURATION_CELL_CURR END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN DURATION_CELL_CURR END) AS PER_75,
MAX(DURATION_CELL_CURR) AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY DURATION_CELL_CURR) AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)B
GROUP BY 1,2,3
下面是我对其动态转换的理解SQL:
REPLACE PROCEDURE PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE (IN COL CHAR(50))
(
BEGIN REQUEST
CALL DBC.SYSEXECSQL
('
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''ACPT'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)A
GROUP BY 1,2,3
UNION ALL
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''PROD'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.PROD_CVM PC
WHERE PC.PW_END_DATE = '2017-01-17'
)B
GROUP BY 1,2,3
')
END REQUEST;
);
我知道在 运行-ready 之前我必须解决许多错误。所以我遇到的第一个错误如下:
谁能帮我解决这个问题。我必须计算 60 多个这样的列的分位数分布,手动操作是疯狂的。 非常感激。 皮尤什
应该删除 BEGIN
之前的一对括号,并且包括日期在内的所有字符串周围的单引号都必须加倍:
REPLACE PROCEDURE NPVAZ_CVM_CHECK_TEST_CASE (IN COL CHAR(50))
BEGIN
CALL DBC.SYSEXECSQL
('
INSERT INTO PROD_CE_WORK_SPACE.NPVAZ_CVM_CHECK_TEST_CASE_5
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''ACPT'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.ACPT_PROD_CVM PC
WHERE PC.PW_END_DATE = DATE ''2017-01-17''
)A
GROUP BY 1,2,3
UNION ALL
SELECT
'||COL||' AS COLMN,
PW_END_DATE,
''PROD'' AS TAB,
MIN( '||COL||') AS PER_MIN,
MIN(CASE WHEN SEQNUM / 0.25 >= CNT THEN '||COL||' END) AS PER_25,
MIN(CASE WHEN SEQNUM / 0.50 >= CNT THEN '||COL||' END) AS PER_50,
MIN(CASE WHEN SEQNUM / 0.75 >= CNT THEN '||COL||' END) AS PER_75,
MAX( '||COL||') AS PER_MAX
FROM (
SELECT PC.*,
ROW_NUMBER() OVER (ORDER BY '||COL||') AS SEQNUM,
COUNT(*) OVER () AS CNT
FROM PROD_EXP_DL_CVM.PROD_CVM PC
WHERE PC.PW_END_DATE = DATE ''2017-01-17''
)B
GROUP BY 1,2,3
');
END;