如何使用PL / SQL和动态日期进行数据透视-新文章

时间:2018-07-07 16:36:07

标签: sql oracle dynamic plsql pivot

我在下面模拟了一些测试数据。谢谢您的投入。真正可以在如何动态调整日期方面使用您的帮助。我也尝试下面的第一个PLSQL代码。这不是很有效。你们能帮我吗?因此,第一部分是获取动态日期。第二部分是使用变量存储的日期进行透视。您认为这是正确的方法吗?真的可以使用一些帮助谢谢您的时间

with t as (
select 27 test_number, 'NCO' src_sys_cd, 'CO' rgn_cd, 'P' clm_type_cd, '06-27-2018' date_without_time, 14 rec_cnt from dual
union all
select 27 test_number, 'NHI' src_sys_cd, 'HI' rgn_cd, 'P' clm_type_cd, '06-28-2018' date_without_time, 15 rec_cnt from dual
union all
select 27 test_number, 'NHI' src_sys_cd, 'HI' rgn_cd, 'P' clm_type_cd, '06-29-2018' date_without_time, 16 rec_cnt from dual
union all
select 27 test_number, 'NHI' src_sys_cd, 'HI' rgn_cd, 'P' clm_type_cd, '06-30-2018' date_without_time, 60 rec_cnt from dual
union all
select 27 test_number, 'NHI' src_sys_cd, 'HI' rgn_cd, 'I' clm_type_cd, '06-30-2018' date_without_time, 60 rec_cnt from dual
union all
select 27 test_number, 'NCO' src_sys_cd, 'CO' rgn_cd, 'P' clm_type_cd, '07-01-2018' date_without_time, 28 rec_cnt from dual
union all
select 27 test_number, 'NCO' src_sys_cd, 'CO' rgn_cd, 'P' clm_type_cd, '07-02-2018' date_without_time, 70 rec_cnt from dual
union all
select 27 test_number, 'NGA' src_sys_cd, 'GA' rgn_cd, 'P' clm_type_cd, '07-03-2018' date_without_time, 80 rec_cnt from dual
union all
select 27 test_number, 'NMA' src_sys_cd, 'MA' rgn_cd, 'P' clm_type_cd, '07-04-2018' date_without_time, 90 rec_cnt from dual
union all
select 27 test_number, 'NSC' src_sys_cd, 'SC' rgn_cd, 'P' clm_type_cd, '07-05-2018' date_without_time, 100 rec_cnt from dual
union all
select 27 test_number, 'NNC' src_sys_cd, 'NC' rgn_cd, 'P' clm_type_cd, '07-06-2018' date_without_time, 20 rec_cnt from dual
union all
select 27 test_number, 'NHI' src_sys_cd, 'HI' rgn_cd, 'P' clm_type_cd, '07-07-2018' date_without_time, 29 rec_cnt from dual
union all
select 27 test_number, 'NHI' src_sys_cd, 'HI' rgn_cd, 'I' clm_type_cd, '07-07-2018' date_without_time, 29 rec_cnt from dual
union all
select 27 test_number, 'NHI' src_sys_cd, 'HI' rgn_cd, 'P' clm_type_cd, '07-08-2018' date_without_time, 28 rec_cnt from dual
)

以下是当前的硬编码SQL:

WITH T AS
          (
            SELECT DISTINCT
              TEST_NUMBER,
              SRC_SYS_CD,
              RGN_CD,
              CLM_TYP_CD,
              TO_CHAR(INSRT_DTTM,'mm-dd-yyyy') AS DATE_WITHOUT_TIME,
              REC_CNT
            FROM result
            WHERE TRUNC(INSRT_DTTM)   >= TO_DATE('05-19-2018', 'MM-DD-YYYY')
            AND TRUNC(INSRT_DTTM) <= TO_DATE('05-25-2018', 'MM-DD-YYYY')
          )
        SELECT *
        FROM  T PIVOT 
          ( 
          SUM(REC_CNT)  -- need an aggregate function, since there is only one row, it should be fine
          FOR DATE_WITHOUT_TIME IN ('05-19-2018','05-20-2018','05-21-2018','05-22-2018','05-23-2018','05-24-2018','05-25-2018') )
        ORDER BY
          TEST_NUMBER,
          SRC_SYS_CD,
          RGN_CD,
          CLM_TYP_CD;

这很好。我想使用以下日期函数替换FOR子句中的硬编码日期。

SELECT TRUNC(sysdate, 'IW') + Level - (1+ TRUNC(sysdate, 'IW') - TRUNC(sysdate, 'IW'))
        FROM dual
        CONNECT BY level <= 8;

这给了我类似的结果:

        DATE_WITHOUT_TIME
        02-JUL-2018 00:00:00
        03-JUL-2018 00:00:00
        04-JUL-2018 00:00:00
        05-JUL-2018 00:00:00
        06-JUL-2018 00:00:00
        07-JUL-2018 00:00:00
        08-JUL-2018 00:00:00
        09-JUL-2018 00:00:00

我想使用此动态日期替换FOR子句中的硬编码日期,但是我之前没有做过任何PLSQL。下面是我的尝试,还不够用。你能帮忙吗?谢谢

       DECLARE
  date_time clob ;
  sqlqry clob;
BEGIN  
SELECT DISTINCT 
--    LISTAGG('''' || DT || ''' AS ' || DT,',') WITHIN GROUP (
    LISTAGG('''' || DT || '''',',') WITHIN GROUP (
  ORDER BY DT)
  INTO DATE_TIME
  FROM
    (SELECT TRUNC(sysdate, 'IW') + Level - (1+ TRUNC(sysdate, 'IW') - TRUNC(sysdate, 'IW')) AS dt
    FROM dual
      CONNECT BY level <= 8 --great
    ) ;
sqlqry:='SELECT DISTINCT
      TEST_NUMBER,
      SRC_SYS_CD,
      RGN_CD,
      CLM_TYP_CD,
      TO_CHAR(trunc(INSRT_DTTM)) AS DATE_WITHOUT_TIME,
      REC_CNT
    FROM CDW_T.DATA_MONITORING_RESULT 
PIVOT 
  ( 
  SUM(REC_CNT)  
  FOR DATE_WITHOUT_TIME IN (@date_time)) 
ORDER BY
  TEST_NUMBER,
  SRC_SYS_CD,
  RGN_CD,
  CLM_TYP_CD'; 

execute immediate sqlqry;
end;

Error report -
ORA-00936: missing expression
ORA-06512: at line 33
00936. 00000 -  "missing expression"
*Cause:    
*Action:

1 个答案:

答案 0 :(得分:0)

您做了所有的辛苦工作,并且快要结束了。不放弃的好工作!发现,在SQL中,如果不了解进阶的所有列,就无法构建枢轴结构。那是如何工作的。让我感到好奇,这真的不可能吗? PL / SQL可以解救!

在程序包中创建了一个过程,该过程以光标形式给出了结果。显示包裹的身体:

create or replace package body test_pck as

procedure get_cursor(p_cursor out sys_refcursor) is

  l_date_list varchar2(4000);
  l_sql varchar2(4000);

begin

  select
    listagg('''' || tmp.date_without_time || '''',',') 
    within group (
    order by tmp.date_without_time)
  into l_date_list
  from(
    select distinct 
      tmp1.date_without_time
    from
      CDW_T.DATA_MONITORING_RESULT) tmp;

  dbms_output.put_line('date_list: '||l_date_list);

  l_sql := '
    select 
      *
    from(
      select
        tmp1.rec_cnt,
        tmp1.date_without_time
      from
        CDW_T.DATA_MONITORING_RESULT tmp1)
    pivot(
      sum(rec_cnt)
      for date_without_time in ( ' || l_date_list || ' ))';

  open p_cursor
  for l_sql;

exception
  when others then
    dbms_output.put_line(sqlcode || ' - ' || sqlerrm);
end get_cursor;
end test_pck;

在“测试”模式(PL / SQL功能)下调用该过程之后:

begin
  -- Call the procedure
  test_pck.get_cursor(p_cursor => :p_cursor);
end;

输出为:

Output

有帮助吗?