Oracle 使用for循环在PL/SQL中按名称选择不同的列

Oracle 使用for循环在PL/SQL中按名称选择不同的列,oracle,plsql,oracle11g,Oracle,Plsql,Oracle11g,现在我有一张这样的桌子 Table name: itemlist Item year value1 value2 value3 value4 value5 ... value99 -------------------------------------- foo1 12 32 48 foo2 13 32 50 foo3 14 32 50 foo4 15 33 48 foo5 16 33 48 foo6 17 33

现在我有一张这样的桌子

Table name: itemlist Item year value1 value2 value3 value4 value5 ... value99 -------------------------------------- foo1 12 32 48 foo2 13 32 50 foo3 14 32 50 foo4 15 33 48 foo5 16 33 48 foo6 17 33 48 foo7 13 38 42 foo8 14 34 44 foo9 15 36 46 foo10 16 37 48 显然它不起作用,问题是我不知道如何将值与索引1-99连接起来

SELECT COUNT( CASE WHEN Value1 > 35 THEN 1 END ) AS v1_number,
       COUNT( CASE WHEN Value2 > 35 THEN 1 END ) AS v2_number,
       COUNT( CASE WHEN Value3 > 35 THEN 1 END ) AS v3_number,
       -- ...
       COUNT( CASE WHEN Value99 > 35 THEN 1 END ) AS v99_number
FROM   itemlist;
然后,您可以执行复制/粘贴和查找/替换更改
使用
创建一个视图。这是一次性的努力。然后,在该视图上执行查询将更容易

因此,首先创建视图(扩展所有值列):

然后可以执行如下查询:

SELECT   item, year,
         SUM(CASE value > 35 THEN 1 END) AS above_35,
         SUM(CASE value < 35 THEN 1 END) AS below_35,
FROM     v_itemlist
GROUP BY item, year;
选择项目,年份,
如上所述的总和(案例值>35,然后为1结束),
总和(案例值<35,则为1端)如下所示,
从v_项目列表
按项目分组,年份;

一旦你习惯了使用这个视图,你可以考虑用这种方式创建你的基表,这样你就可以从索引中受益,并且可以方便地单独插入和删除值,排序它们,检测重复。等等。这就是关系数据库的建模方式,并提供最佳价值。

我对trincot的答案投了赞成票,但也许你正在寻找类似的答案

create or replace function eval(tab in varchar2, col in varchar2, cond in varchar2) return number as
    ret number; 
begin
    execute immediate 'select count(*) from '||tab||' where '||col||cond into ret;
    return ret;
end;

选择表名、列名、,

eval(table_name,column_name,“>35”)、eval(table_name,column_name,”,这是数据非规范化时遇到的问题。如果每个项目、年份和值都有一行,那么查询就会很简单。@eli,这些答案对您有帮助吗?您能评论或接受吗?
SET SERVEROUTPUT ON;
VARIABLE cur REFCURSOR;

DECLARE
  qry  CLOB := EMPTY_CLOB();
  line_above VARCHAR2(4000);
  line_below VARCHAR2(4000);
BEGIN
  FOR i IN 1 .. 99 LOOP
    line_above := ', COUNT( CASE WHEN Value' || i || ' > 35 THEN 1 END ) AS v' || i || '_above_number';
    line_below := ', COUNT( CASE WHEN Value' || i || ' < 35 THEN 1 END ) AS v' || i || '_below_number';
    qry := qry || line_above || line_below;
  END LOOP;
  qry := 'SELECT' || SUBSTR( qry, 2 ) || ' FROM itemlist';
  DBMS_OUTPUT.PUT_LINE( qry );
  OPEN :cur FOR qry;
END;
/

PRINT :cur;
CREATE VIEW v_itemlist AS
    SELECT  *
    FROM    unpivot_test
    UNPIVOT (value FOR value_id IN (
                value1 AS 1,
                value2 AS 2,
                value3 AS 3,
                ...
                value98 AS 98,
                value99 AS 99
            ));
SELECT   item, year,
         SUM(CASE value > 35 THEN 1 END) AS above_35,
         SUM(CASE value < 35 THEN 1 END) AS below_35,
FROM     v_itemlist
GROUP BY item, year;
create or replace function eval(tab in varchar2, col in varchar2, cond in varchar2) return number as
    ret number; 
begin
    execute immediate 'select count(*) from '||tab||' where '||col||cond into ret;
    return ret;
end;
select table_name, column_name, 
eval(table_name, column_name, '>35'), eval(table_name, column_name, '<35') 
from all_tab_columns 
where table_name = upper('itemlist') and column_name like 'value%' /*and data_type = 'NUMBER'*/