我可以使用表中的条目创建构建动态where子句

时间:2013-01-17 14:20:50

标签: sql teradata

我有一个元数据表如下:

RULE_NAME      COL_NAME   COL_VAL
RULE_1     COL_1         ABC
RULE_1     COL_5         XYZ
RULE_2     COL_2         123
RULE_2     COL_3         A2d5
RULE_2     COL_8         X0IL
RULE_3     COL_1         PQR
RULE_3     COL_7         9789

我需要使用此表中的数据生成WHERE子句。 WHERE子句应该是这样的:

WHERE
(COL_1 = 'ABC' AND COL_5 = 'XYZ') --from Rule 1 records
OR
(COL_2 = '123' AND COL_3 = 'A2D5' AND COL_8 = 'X0IL') --From Rule 2 records
OR
(COL_1 = 'PQR' AND COL_7 = '9789') --from Rule 3 records

这可能与普通的SQL(我在Teradata上)有关吗?有人可以给我一些关于如何实现这个目标的指示吗?

感谢。

3 个答案:

答案 0 :(得分:2)

以下单行返回每个子句:

select oreplace(max(case when seqnum = 1 then clause else '' end) ||
                MAX(case when seqnum = 2 then clause else '' end) ||
                MAX(case when seqnum = 3 then clause else '' end)
               ), ')(', ') and (')
from (select t.*, ROW_NUMBER() over (partition by rule_name order by col_name) as seqnum,
             ('(' || COL_NAME || ' = ' || '''' || col_val || ''')') as clause
      from t
     ) t
group by rule_name

这足够接近吗?

如果您没有'oreplace'功能,可以执行以下操作:

select max(case when seqnum = 1 then clause else '' end) ||
       MAX(case when seqnum = 2 then clause else '' end) ||
       MAX(case when seqnum = 3 then clause else '' end) || ' 1=1 OR'
from (select t.*, ROW_NUMBER() over (partition by rule_name order by col_name) as seqnum,
             ('(' || COL_NAME || ' = ' || '''' || col_val || ''') and') as clause
      from t
     ) t
group by rule_name

答案 1 :(得分:0)

你尝试过这样的事情(未经测试)吗?也许你可以提供你想要的结果。

SELECT *
FROM TableName
WHERE 
(
   (COL_Name = 'COL_1' AND COL_Val = 'ABC') 
   OR (COL_Name = 'COL_5' AND COL_Val = 'XYZ')
)
OR 
(
   (COL_Name = 'COL_2' AND COL_Val = '123') 
   OR (COL_Name = 'COL_3' AND COL_Val = 'A2D5') 
   OR (COL_Name = 'COL_8' AND COL_Val = 'X0IL')
) 
OR 
(
   (COL_Name = 'COL_1' AND COL_Val = 'PQR') 
   OR (COL_Name = 'COL_7' AND COL_Val = '9789')
)

答案 2 :(得分:0)

这是基于scott.emp表的一般Oracle示例。涵盖EXECUTE IMMEDIATE和REF CURSOR:

DECLARE
  v_sql           VARCHAR2(200);
  v_tab_name      VARCHAR2(200):= 'scott.emp';
  v_field_name    VARCHAR2(200):= 'job';
  v_list          VARCHAR2(200):= '''MANAGER'', ''CLERK''';
BEGIN
  v_sql:= 'SELECT * FROM '|| v_tab_name ||' WHERE '||v_field_name ||' IN (:v)';
  EXECUTE IMMEDIATE v_sql USING v_list;
  dbms_output.put_line(v_sql);
END;
/

DECLARE
  emp_cur_rc      SYS_REFCURSOR;
  emp_rec         scott.emp%ROWTYPE;
--
  v_sql           VARCHAR2(200);
  v_tab_name      VARCHAR2(200):= 'scott.emp';
  v_field_name    VARCHAR2(200):= 'job';
  v_list          VARCHAR2(200):= '''MANAGER'', ''CLERK''';
BEGIN
  v_sql:= 'SELECT * FROM '|| v_tab_name ||' WHERE '||v_field_name ||' IN ('||v_list||')';
  EXECUTE IMMEDIATE v_sql;
  dbms_output.put_line('EXECUTE IMMEDIATE example: '||v_sql||chr(13));
--
  OPEN emp_cur_rc FOR v_sql;
  LOOP
    FETCH emp_cur_rc INTO emp_rec;
    EXIT WHEN emp_cur_rc%NOTFOUND;
    dbms_output.put_line('REFCURSOR example: '||emp_rec.empno||chr(9)||emp_rec.ename||chr(9)||emp_rec.job);
  END LOOP;
  CLOSE emp_cur_rc;
END;
/