是否可以将以下Oracle SQL查询转换为动态查询?我的意思是,我已经将案例陈述的值硬编码为'INTERNET','SALES'ETC ......是否可以避免硬编码?我的源列是动态的。我在想一个for循环和数组,但在SQL中是否可用?如果有人能让我继续这样做,那就太好了。谢谢。
SELECT
NVL(status, 'Grand Total') AS "ROW LABELS",
COUNT(case when source = 'INTERNET' THEN 1 end) AS "INTERNET",
COUNT(case when source = 'SALES' THEN 1 end) AS "SALES",
COUNT(case when source = 'DEMO' THEN 1 end) AS "DEMO",
COUNT(case when source = 'COM' THEN 1 end) AS "COM",
COUNT(CASE WHEN order_source IN ('INTERNET', 'SALES', 'DEMO', 'COM') THEN 1 END) AS "Grand Total"
FROM
SOMETABLE
GROUP BY ROLLUP(status);
答案 0 :(得分:2)
你无法在纯SQL中真正做到这一点。你可以创建一个动态生成结果的函数;可能比使用匿名块更容易处理:
create or replace function get_counts return sys_refcursor as
query varchar2(32767);
rc sys_refcursor;
begin
query := 'select nvl(status, ''Grand Total'') as row_labels';
for tmp in (select distinct source from sometable order by 1)
loop
query := query || ', count(case when source = ''' || tmp.source
|| ''' then 1 end) as "' || substr(tmp.source, 1, 30) || '"';
end loop;
query := query || ', count(*) as total';
query := query || ' from sometable';
query := query || ' group by rollup(status)';
query := query || ' order by status';
open rc for query;
return rc;
end;
/
在SQL * Plus或SQL Developer中运行(使用“作为脚本运行”):
var rc refcursor;
exec :rc := get_counts;
print rc
您也可以将此作为查询:
select get_counts from dual;
在SQL Developer中,在查询输出窗口中显示无用的显示,但如果双击该值(看起来像{<ROW_LABELS=...>}
),则会在最右侧显示一个编辑图标;单击该按钮,实际值将显示在新窗口中。
我假设'总'应该包括一切;如果不是,我不确定你如何确定动态包含什么。如果你可以这样做,虽然你可以保留一个单独的变量或集合,在循环时为总计构建case语句,然后再添加它。
答案 1 :(得分:2)
您需要具有动态列定义的PIVOT函数。最简单的方法是pivot xml:
create table tst_data (id int primary key, source varchar2(255));
insert into tst_data values (1, 'INTERNET');
insert into tst_data values (2, 'DEMO');
insert into tst_data values (3, 'INTERNET');
insert into tst_data values (4, 'SALES');
insert into tst_data values (5, 'INTERNET');
insert into tst_data values (6, 'DEMO');
insert into tst_data values (7, 'INTERNET');
insert into tst_data values (8, 'COM');
commit;
select * from (
select source from tst_data
)
pivot xml
(
count(1)
for source in (select distinct t.source from tst_data t)
)
需要处理XML数据后:
<PivotSet>
<item>
<column name = "SOURCE">COM</column>
<column name = "COUNT(1)">1</column>
</item>
<item>
<column name = "SOURCE">DEMO</column>
<column name = "COUNT(1)">2</column>
</item>
<item>
<column name = "SOURCE">INTERNET</column>
<column name = "COUNT(1)">4</column>
</item>
<item>
<column name = "SOURCE">SALES</column>
<column name = "COUNT(1)">1</column>
</item>
</PivotSet>
PIVOT XML
支持动态列定义(for source in (select distinct t.source from tst_data t)
),但它返回XML数据。 Extractvalue
和xmltable
函数允许从服务器端的XML查询特定列,但您必须提前指定字段名称。所以我假设在客户端解析它。
如果你想在DB层上做所有事情,还有另一种方法。 PIVOT
(不是XML)需要列名for source in ('INTERNET', 'DEMO', 'COM', ...)
。可以生成这样的查询并将游标返回给客户端:
CREATE OR REPLACE FUNCTION FUNCTION1 RETURN SYS_REFCURSOR AS
cur sys_refcursor;
BEGIN
open cur for 'select * from dual'; // generate PIVOT query here
RETURN cur;
END FUNCTION1;
我不知道从游标(在服务器端)创建简单的无类型查询的任何方法,因此如果您希望使用纯SQL查询,请分两步执行: