我需要展平一个表,但这里是一个棘手的部分,clomuns是动态的,当添加包含新ID的新记录时,查询应该有效。
这是我的工作查询(简化了IN,这实际上是数百个值):
SELECT *
FROM (select qv.respnr, sq.question_id, qv.question_value
from survey_question sq, question_values qv
where qv.question_id = sq.question_id
and sq.survey_id = 1
order by qv.respnr, page, ranked)
PIVOT (
MAX(question_value) --<-- pivot_clause
FOR question_id --<-- pivot_for_clause
IN (346 as c346,347 as c347)
)
我想用这样的内容替换IN (346 as c346,347 as c347)
:
SELECT mq.question_id
FROM meta_question mq, survey_question sq2
WHERE sq2.survey_id = 1
AND mq.question_id = sq2.question_id
ORDER BY page, ranked
知道怎么做吗?
我注意到IN不能只是带有select语句的fileld,所以这不起作用:
IN (SELECT mq.question_id
FROM meta_question mq, survey_question sq2
WHERE sq2.survey_id = 1
AND mq.question_id = sq2.question_id
ORDER BY page, ranked)
答案 0 :(得分:2)
SQL中所有列的名称和类型需要在编译时知道,在这里您必须使用dynamic SQL,因为您希望根据数据更改的列数。
如果您使用PL / SQL,则可以使用ref cursor:
DECLARE
l_rc SYS_REFCURSOR;
l_dynamic_query VARCHAR2(32000);
BEGIN
FOR cc IN (SELECT mq.question_id
FROM meta_question mq, survey_question sq2
WHERE sq2.survey_id = 1
AND mq.question_id = sq2.question_id
ORDER BY page, ranked) LOOP
-- build dynamic query here
END LOOP;
OPEN l_rc FOR '
SELECT *
FROM (SELECT qv.respnr, sq.question_id, qv.question_value
FROM survey_question sq, question_values qv
WHERE qv.question_id = sq.question_id
AND sq.survey_id = 1
ORDER BY qv.respnr, page, ranked)
PIVOT ( MAX (question_value) --<-- pivot_clause
FOR question_id --<-- pivot_for_clause
IN (' || l_dynamic_query || ')
)';
-- process l_rc (LOOP..FETCH..CLOSE)
END;
您也可以使用DBMS_SQL
。
答案 1 :(得分:1)
由于必须知道pivot
中的列,因此您需要使用动态SQL来生成结果。我通常使用ref_cursor生成一个过程来执行类似这样的任务:
CREATE OR REPLACE procedure dynamic_pivot_q(p_cursor in out sys_refcursor)
as
sql_query varchar2(8000) := 'select qv.respnr ';
begin
for x in (select distinct question_id, mname from meta_question order by 1)
loop
sql_query := sql_query ||
' , max(case when mq.question_id = '||x.question_id||' then qv.question_value else null end) as "c'||x.mname||'"';
dbms_output.put_line(sql_query);
end loop;
sql_query := sql_query || ' from meta_question mq
left join survey_question sq
on mq.question_id = sq.question_id
and sq.survey_id = 1
inner join question_values qv
on qv.question_id = sq.question_id
and sq.survey_id = 1
group by qv.respnr';
dbms_output.put_line(sql_query);
open p_cursor for sql_query;
end;
/
然后你可以按照以下方式执行它(注意:这是我在TOAD中使用的代码):
variable x refcursor
exec dynamic_pivot_q(:x)
print x