生成动态列值SQL
我有两张桌子。我需要根据配置表列形成一个比率。因为100只有损益栏,所以比率应该是损益。这是否需要动态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
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'
);
有关可运行的示例,请参阅
有关此解决方案的一些注意事项:
列顺序
值您可以使用
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'
);
有关可运行的示例,请参阅
有关此解决方案的一些注意事项:
列顺序
值我不明白表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只有…”是否意味着一些表在配置表中会有两列以上;如果是这样,你希望发生什么?或您是否专门在配置表中查找损益,而忽略其他所有内容?不清楚您是否在配置中查找列名;或者只寻找固定的名字。