Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/oracle/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
生成动态列值SQL_Sql_Oracle_Oracle11g - Fatal编程技术网

生成动态列值SQL

生成动态列值SQL,sql,oracle,oracle11g,Sql,Oracle,Oracle11g,我有两张桌子。我需要根据配置表列形成一个比率。因为100只有损益栏,所以比率应该是损益。这是否需要动态SQL 我试着写,但我不知道该怎么写。你能推荐一下吗 配置表: WITH col as (SELECT COLUMN_NAME FROM config WHERE TABLE_NAME='A100' ) , fetch_col as ( SELECT DISTINCT C

我有两张桌子。我需要根据配置表列形成一个比率。因为100只有损益栏,所以比率应该是损益。这是否需要动态SQL

我试着写,但我不知道该怎么写。你能推荐一下吗

配置表:

    WITH col as (SELECT  COLUMN_NAME
             FROM   config
             WHERE TABLE_NAME='A100' 
            ) ,
            
 fetch_col as (    SELECT DISTINCT CUSTOMER,COLUMN_NAME,SALES,PROFIT,LOSS,DIVIDEND
                   FROM A100 CROSS JOIN dba_tab_columns 
                   WHERE COLUM_NAME IN (SELECT COLUMN_NAME FROM col)    
            )
   SELECT  CUSTOMER,PROFI||':'||LOSS
            CASE WHEN a.COLUMN_NAME=b.COLUMN_NAME THEN PROFIT||':'||LOSS ELSE '' END         
   FROM fetch_col a INNER JOIN col b
   ON a.COLUMN_NAME=b.COLUMN_NAME

表格-A100

输出:我需要根据表1和表2形成一个比率

我尝试的查询:

    WITH col as (SELECT  COLUMN_NAME
             FROM   config
             WHERE TABLE_NAME='A100' 
            ) ,
            
 fetch_col as (    SELECT DISTINCT CUSTOMER,COLUMN_NAME,SALES,PROFIT,LOSS,DIVIDEND
                   FROM A100 CROSS JOIN dba_tab_columns 
                   WHERE COLUM_NAME IN (SELECT COLUMN_NAME FROM col)    
            )
   SELECT  CUSTOMER,PROFI||':'||LOSS
            CASE WHEN a.COLUMN_NAME=b.COLUMN_NAME THEN PROFIT||':'||LOSS ELSE '' END         
   FROM fetch_col a INNER JOIN col b
   ON a.COLUMN_NAME=b.COLUMN_NAME

我试着解决你的问题。也许它还不合适

我通过“column_type”列扩展了表“config”,以确定哪个条目表示分子,哪个分母

CREATE OR REPLACE PACKAGE pkg_demo
AS
   TYPE r_out IS RECORD
      ( table_name   VARCHAR2(30),
        customer     VARCHAR2(30),
        ratio        VARCHAR2(30)
      );
   TYPE t_out IS TABLE OF r_out;

   FUNCTION get_ratio ( i_table  IN VARCHAR2 )
      RETURN t_out PIPELINED;
   
END pkg_demo;
/

CREATE OR REPLACE PACKAGE BODY pkg_demo
AS

   FUNCTION get_ratio ( i_table  IN VARCHAR2 )
      RETURN t_out PIPELINED
   AS
      l_num config.column_name%TYPE;
      l_den config.column_name%TYPE;
      l_sql VARCHAR2(32767);
      TYPE cur_type IS REF CURSOR;
      l_cur cur_type;
      l_rec r_out;
   BEGIN
      SELECT config.column_name
        INTO l_num
        FROM config
       WHERE table_name = i_table
         AND column_type = 'N';
      
      SELECT config.column_name
        INTO l_den
        FROM config
       WHERE table_name = i_table
         AND column_type = 'D';

      l_sql := 'SELECT ''' || TRIM(LEADING 'A' FROM i_table) || ''', customer, TO_CHAR(' || l_num || ') ||'':''|| TO_CHAR('|| l_den || ', ''FM00'') FROM ' || i_table;
      
      OPEN l_cur FOR l_sql;
      LOOP
         FETCH l_cur INTO l_rec;
         EXIT WHEN l_cur%NOTFOUND;
         
         PIPE ROW(l_rec);
      END LOOP;
      
      CLOSE l_cur;
         
   END get_ratio;
   
END pkg_demo;
/

SELECT * FROM TABLE(pkg_demo.get_ratio('A100'));
结果:

TABLE_NAME  CUSTOMER  RATIO                         
----------- --------- ---------
100         Microsoft 10:01                         
100         Tesla     15:02     

我试着解决你的问题。也许它还不合适

我通过“column_type”列扩展了表“config”,以确定哪个条目表示分子,哪个分母

CREATE OR REPLACE PACKAGE pkg_demo
AS
   TYPE r_out IS RECORD
      ( table_name   VARCHAR2(30),
        customer     VARCHAR2(30),
        ratio        VARCHAR2(30)
      );
   TYPE t_out IS TABLE OF r_out;

   FUNCTION get_ratio ( i_table  IN VARCHAR2 )
      RETURN t_out PIPELINED;
   
END pkg_demo;
/

CREATE OR REPLACE PACKAGE BODY pkg_demo
AS

   FUNCTION get_ratio ( i_table  IN VARCHAR2 )
      RETURN t_out PIPELINED
   AS
      l_num config.column_name%TYPE;
      l_den config.column_name%TYPE;
      l_sql VARCHAR2(32767);
      TYPE cur_type IS REF CURSOR;
      l_cur cur_type;
      l_rec r_out;
   BEGIN
      SELECT config.column_name
        INTO l_num
        FROM config
       WHERE table_name = i_table
         AND column_type = 'N';
      
      SELECT config.column_name
        INTO l_den
        FROM config
       WHERE table_name = i_table
         AND column_type = 'D';

      l_sql := 'SELECT ''' || TRIM(LEADING 'A' FROM i_table) || ''', customer, TO_CHAR(' || l_num || ') ||'':''|| TO_CHAR('|| l_den || ', ''FM00'') FROM ' || i_table;
      
      OPEN l_cur FOR l_sql;
      LOOP
         FETCH l_cur INTO l_rec;
         EXIT WHEN l_cur%NOTFOUND;
         
         PIPE ROW(l_rec);
      END LOOP;
      
      CLOSE l_cur;
         
   END get_ratio;
   
END pkg_demo;
/

SELECT * FROM TABLE(pkg_demo.get_ratio('A100'));
结果:

TABLE_NAME  CUSTOMER  RATIO                         
----------- --------- ---------
100         Microsoft 10:01                         
100         Tesla     15:02     

您可以使用
DBMS_XMLGEN.GETXML
在单个SQL语句中生成动态列:

--Convert the XML to relational data.
select table_name, customer, ratio
from
(
    --Convert the SQL statement into XML results.
    select XMLType(dbms_xmlgen.getXML(sql)) results
    from
    (
        --Generate a SQL statement with column names based on configuration.
        select table_name,
            replace(replace(replace(
                q'[select '#TABLE_NAME#' table_name, customer, #COLUMN_1# || ':' || #COLUMN_2# ratio from #TABLE_NAME#]'
            , '#TABLE_NAME#', table_name)
            , '#COLUMN_1#', max(column_name) keep(dense_rank first order by column_order))
            , '#COLUMN_2#', max(column_name) keep(dense_rank first order by column_order desc)) sql
        from config
        group by table_name
    )
)
cross join
xmltable
(
    '/ROWSET/ROW'
    passing results
    columns
        table_name varchar2(128) path 'TABLE_NAME',
        customer   varchar2(128) path 'CUSTOMER',
        ratio      varchar2(128) path 'RATIO'
);
有关可运行的示例,请参阅

有关此解决方案的一些注意事项:

  • 这种XML技巧仅在具有设置数量的动态列时有效
  • 您希望尽可能避免这种动态解决方案。SQL中的动态SQL有时是不可避免的,但通常有一种方法可以改进数据模型,使SQL更简单。或者,这种类型的动态代码最好由应用程序处理
  • 正如Thomas Kirchhoff所指出的,解决方案需要某种方式来知道哪个列先到,所以我添加了一个
    列顺序
  • 与Thomas的解决方案相比,我的解决方案更小,并且不需要创建其他对象。另一方面,我的解决方案更神秘,运行速度会更慢。哪个答案最好可能取决于您使用这些查询的频率。如果这是一个罕见的查询,那么只需使用DBMS_XMLGEN并完成它就更简单了。如果这是一个常见的查询,那么创建和维护一个包来简化查询是值得的

  • 您可以使用
    DBMS_XMLGEN.GETXML
    在单个SQL语句中生成动态列:

    --Convert the XML to relational data.
    select table_name, customer, ratio
    from
    (
        --Convert the SQL statement into XML results.
        select XMLType(dbms_xmlgen.getXML(sql)) results
        from
        (
            --Generate a SQL statement with column names based on configuration.
            select table_name,
                replace(replace(replace(
                    q'[select '#TABLE_NAME#' table_name, customer, #COLUMN_1# || ':' || #COLUMN_2# ratio from #TABLE_NAME#]'
                , '#TABLE_NAME#', table_name)
                , '#COLUMN_1#', max(column_name) keep(dense_rank first order by column_order))
                , '#COLUMN_2#', max(column_name) keep(dense_rank first order by column_order desc)) sql
            from config
            group by table_name
        )
    )
    cross join
    xmltable
    (
        '/ROWSET/ROW'
        passing results
        columns
            table_name varchar2(128) path 'TABLE_NAME',
            customer   varchar2(128) path 'CUSTOMER',
            ratio      varchar2(128) path 'RATIO'
    );
    
    有关可运行的示例,请参阅

    有关此解决方案的一些注意事项:

  • 这种XML技巧仅在具有设置数量的动态列时有效
  • 您希望尽可能避免这种动态解决方案。SQL中的动态SQL有时是不可避免的,但通常有一种方法可以改进数据模型,使SQL更简单。或者,这种类型的动态代码最好由应用程序处理
  • 正如Thomas Kirchhoff所指出的,解决方案需要某种方式来知道哪个列先到,所以我添加了一个
    列顺序
  • 与Thomas的解决方案相比,我的解决方案更小,并且不需要创建其他对象。另一方面,我的解决方案更神秘,运行速度会更慢。哪个答案最好可能取决于您使用这些查询的频率。如果这是一个罕见的查询,那么只需使用DBMS_XMLGEN并完成它就更简单了。如果这是一个常见的查询,那么创建和维护一个包来简化查询是值得的

  • 我不明白表1与此有什么关系。我需要阅读表1来检查要使用哪些列来形成比率,然后阅读表2以基于它形成比率,以便您的配置表将始终有表-A100的2个值?因为定量仅包括2个值。为什么使用distinct?是的distinct不需要,现在更新。它只有两个valuesHow您知道它应该是'PROFIT:LOSS'而不是'LOSS:PROFIT'吗?配置表是否有另一列指示顺序?“因为100只有…”是否意味着一些表在配置表中会有两列以上;如果是这样,你希望发生什么?或您是否专门在配置表中查找损益,而忽略其他所有内容?不清楚您是否在配置中查找列名;或者只查找固定名称。我不知道表1与此有什么关系。我需要阅读表1以检查用于形成比率的列,然后阅读表2以基于它形成比率,以便您的配置表始终具有表-A100的2个值?因为定量仅包括2个值。为什么使用distinct?是的distinct不需要,现在更新。它只有两个valuesHow您知道它应该是'PROFIT:LOSS'而不是'LOSS:PROFIT'吗?配置表是否有另一列指示顺序?“因为100只有…”是否意味着一些表在配置表中会有两列以上;如果是这样,你希望发生什么?或您是否专门在配置表中查找损益,而忽略其他所有内容?不清楚您是否在配置中查找列名;或者只寻找固定的名字。