How to write a dynamic SQL code in Teradata?

拜拜、爱过 提交于 2019-12-12 04:15:33

问题


I am trying to convert this code (which accepts a column name as input, does calculations on the input column and inserts data into a table). Now that I know that we can't pass table/column names through a stored proc or macro, I came to know that we can do it through a dynamic SQL. I am not sure how the syntax should be as I could not find a clear and easy example. Below is my code which needs to be converted:

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

Below is my understanding of its conversion in dynamic 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;
);

I understand I have to resolve many errors before this code is run-ready. So one of the first errors I am getting is below:

Can anyone please help me with this. I have to calculate quantile distribution of 60+ such columns which doing manually is insane. Much appreciated. Piyush


回答1:


The pair of parens starting before the BEGIN should be removed and all single quotes around strings including the dates must be doubled:

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;


来源:https://stackoverflow.com/questions/41869526/how-to-write-a-dynamic-sql-code-in-teradata

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!