2

我需要展平一个表,但这里是棘手的部分,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)
4

2 回答 2

2

SQL 中所有列的名称和类型需要在编译时知道,在这里您将不得不使用动态 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.

于 2013-02-26T15:30:29.667 回答
1

由于必须知道 a 中的列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
于 2013-02-26T15:40:07.497 回答