문제

데이터베이스에 테이블이 있고 user_answers 이는 사용자에게 줄이있는 일련의 질문에 대한 답변을 저장합니다. user_id, question_id, answer_id 그리고 text_entry. 질문 텍스트 및 답변 텍스트 (있는 경우)는 조회 테이블에 저장됩니다. 세 가지 유형의 질문, 단일 응답 질문, 다중 응답 질문 및 텍스트 입력 질문이 있습니다. 따라서 단일 사용자는 다음과 같은 항목이있을 수 있습니다. user_answers 테이블:

user_id    question_id    answer_id    text_entry
-------    -----------    ---------    ----------
  123          100          1010         (null)
  123          200          2010         (null)
  123          200          2030         (null)
  123          300          3000       "code 789"

말하자 questions_text 테이블은 다음과 같습니다.

question_id         text
-----------    -------------
    100           "Gender"
    200         "Interests"
    300         "Your code"

그리고 answers_text 테이블은 다음과 같습니다.

answer_id       text
---------    -----------
   1010       "Female"
   1020        "Male"
   2010       "Sports"
   2020      "Computers"
   2030       "Movies"
   3000        (null)

사용자가 다음과 같은 답을 보여주는 user_id 당 한 줄로 데이터를 CSV로 추출하고 싶습니다.

User,Gender,Sports,Computers,Movies,Code
123,Female,1,0,1,code 789

SQLPLUS를 통해 CSV 파일을 생성하는 방법을 알고 있습니다 (제어 할 수없는 이유로 SQLPLUS를 통해 DB에 액세스 할 수 있습니다 ...) 그러나 PL/SQL 문을 생성하는 방법을 모르겠습니다.

PL/SQL에서 나는 성별 질문의 피벗을 생성 할 수 있다는 것을 알고 있습니다.

SELECT
   user_id || ',' ||
   MIN(DECODE(question_id, '100', (SELECT text FROM answers_text where answer_id = answer_text.answer_id)))
FROM user_answers
GROUP BY user_id
ORDER BY user_id
;

(저는 SQL 사람이 아니므로 인터넷에서 복사됩니다!)

이 코드는 (적어도 내 테스트가 나에게 말하는 한) 단일 응답 질문에 적합하지만 다중 응답 또는 텍스트 입력 유형 질문에서는 작동하지 않습니다.

나는 온라인에서 어떤 것들을 사용하는 것을 보았다 case PL/SQL과 같은 명령문 :

MIN(CASE WHEN question_id = '200' AND answer_id = '2010' THEN '1' ELSE '0' END)

...하지만 답을 열로 가져 오는 방법을 알 수 없습니다. 그리고 내가 찾을 수있는 모든 질문은 SQL-Server와 관련이 있습니다.

단일 PL/SQL 문에서 원하는 출력을 생성하는 방법이 있습니까? 바람직하게는 테이블의 데이터에 의존하지 않는 방식으로 작성해야합니다.

도움이 되었습니까?

해결책

당신이 찾고있는 것을 달성하기 위해 (이 데이터에만 국한되지는 않습니다) 테이블에 여분의 필드가 필요할 것이라고 생각합니다. 예를 들어, 데이터를 보지 않고도 단일 응답, 멀티 응답 및 텍스트 입력이 어떤 질문인지 알아야합니다. 또한 데이터를 링크하지 않고 다중 응답 질문에 어떤 답변이 가능한지 알아야합니다. 여기에서 각 질문 / 답변 조합에 대한 메타 정보를 살펴보고 원하는 형식으로 데이터를 반환 할 수있는 쿼리를 작성할 수 있습니다. 같은 것 :

/* Create Tables with Data - Note 2 new columns added to questions_text */
create table user_answers
as
 select 123 user_id, 100 question_id, 1010 answer_id, null text_entry from dual
 union all
 select 123 user_id, 200 question_id, 2010 answer_id, null text_entry from dual
 union all
 select 123 user_id, 200 question_id, 2030 answer_id, null text_entry from dual
 union all
 select 123 user_id, 300 question_id, 3000 answer_id, 'code 789' text_entry from dual;

create table questions_text
as
 select 100 question_id, 'Gender' question_text, 'S' question_type, 1000 answer_set_id from dual
 union all
 select 200 question_id, 'Interests' question_text, 'M' question_type, 2000 answer_set_id from dual
 union all
 select 300 question_id, 'Your code' question_text, 'T' question_type, 3000 answer_set_id from dual;

create table answers_text
as
 select 1010 answer_id, 'Female' text, 1000 answer_set_id from dual
 union all
 select 1020 answer_id, 'Male' text, 1000 answer_set_id from dual
 union all
 select 2010 answer_id, 'Sports' text, 2000 answer_set_id from dual
 union all
 select 2020 answer_id, 'Computers' text, 2000 answer_set_id from dual
 union all
 select 2030 answer_id, 'Movies' text, 2000 answer_set_id from dual
 union all
 select 3000 answer_id, null text, 3000 answer_set_id from dual;


/* PL/SQL for creating SQL statement to return data in desired format */
declare
 v_sql VARCHAR2(32767);
begin
 v_sql := 'select ua.user_id "User",';
 FOR question IN (
  select question_id, question_text, question_type, answer_set_id
  from questions_text
 )
 LOOP
  IF question.question_type = 'M'
  THEN
   FOR answer IN (
    select answer_id, text
    from answers_text
    where answer_set_id = question.answer_set_id
   )
   LOOP
    v_sql := v_sql||chr(10)||'max(case when ua.question_id = '||question.question_id||' and ua.answer_id = '||answer.answer_id||' then 1 else 0 end) "'||answer.text||'",';
   END LOOP;
  ELSIF question.question_type = 'S'
  THEN
   v_sql := v_sql||chr(10)||'min(case when ua.question_id = '||question.question_id||' then at.text end) "'||question.question_text||'",';
  ELSIF question.question_type = 'T'
  THEN
   v_sql := v_sql||chr(10)||'min(case when ua.question_id = '||question.question_id||' then ua.text_entry end) "'||question.question_text||'",';
  END IF;
 END LOOP;
 v_sql := rtrim(v_sql,',');
 v_sql := v_sql||' from
 user_answers ua
 inner join questions_text qt
  on qt.question_id = ua.question_id
 inner join answers_text at
  on at.answer_id = ua.answer_id
 group by
  ua.user_id';
 -- replace dbms_output with code to write file
 dbms_output.put_line(v_sql);
END;

다른 팁

열이 알려지지 않은 쿼리는 기껏해야 문제가됩니다. 데이터가 어떻게 생겼는지 알지 못하겠습니까? 당신은 이것을보고 싶을 수도 있습니다 톰에게 물어보세요 필요한 결과를 얻을 수있는 패키지에 대한 응답.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top