database.sarang.net
UserID
Passwd
Database
DBMS
MySQL
ㆍPostgreSQL
Firebird
Oracle
Informix
Sybase
MS-SQL
DB2
Cache
CUBRID
LDAP
ALTIBASE
Tibero
DB 문서들
스터디
Community
공지사항
자유게시판
구인|구직
DSN 갤러리
도움주신분들
Admin
운영게시판
최근게시물
PostgreSQL Q&A 6912 게시물 읽기
No. 6912
generate_series 질문 드립니다.
작성자
tyro
작성일
2006-11-26 18:27ⓒ
2006-11-26 18:36ⓜ
조회수
4,017

안녕하세요
아주 간만에 질문 하나 드립니다.

시험문제가 있고 학생들이 답을 합니다.

문제는 총 3개 이며, 각각에 대한 문항수는 5 개 입니다.


답변 테이블에 이런식으로 저장이 됩니다.


q
--------
{1,1,3}
{2,2,2}
{1,4,2}
...

q 는 배열요소 순서는 문제번호 순서이고
해당 레코드들은 각 번호에 대한 기입한 답입니다.

즉, 첫번째 레코드는 문제1번에 답을 1 2번도 1 3번은 3 을 답한 경우입니다.


그 데이타를 이용하여 출력할 내용은 각 문제들에 대하여
1번을 답한거 몇개, 2번을 답한거 몇개...... 5번을 답한거 몇개.. 를 내는 것입니다.

즉..


no s1 s2 s3 s4 s5
------------------
1    2   1   0   0   0
2    1   1   0   1   0
3    0   2   1   0   0

이런식이 되겠죠..
(no: 문제번호, s1 ~s5: 문항)

이것을 풀기 위해 유니온을 사용하였씁니다.


select no,s1,s2,s3,s4,s5 from 
(
    (select 1 as no,
     sum(case q[1] when 1 then 1 else 0 end) as s1,
     sum(case q[1] when 2 then 1 else 0 end) as s2,
     sum(case q[1] when 3 then 1 else 0 end) as s3,
     sum(case q[1] when 4 then 1 else 0 end) as s4,
     sum(case q[1] when 5 then 1 else 0 end) as s5
     from ans where q[1] is not null
    )
  union all
    (select 2 as no,
     sum(case q[2] when 1 then 1 else 0 end) as s1,
     sum(case q[2] when 2 then 1 else 0 end) as s2,
     sum(case q[2] when 3 then 1 else 0 end) as s3,
     sum(case q[2] when 4 then 1 else 0 end) as s4,
     sum(case q[2] when 5 then 1 else 0 end) as s5
     from ans where q[2] is not null
    )
  union all
    (select 3 as no,
     sum(case q[3] when 1 then 1 else 0 end) as s1,
     sum(case q[3] when 2 then 1 else 0 end) as s2,
     sum(case q[3] when 3 then 1 else 0 end) as s3,
     sum(case q[3] when 4 then 1 else 0 end) as s4,
     sum(case q[3] when 5 then 1 else 0 end) as s5
     from ans where q[3] is not null
    )                                                           
) t
order by no                                


이렇게 하면 답은 나옵니다만..

문제가 3개에 거치지 않고, 10개, 20 개 25개 정도로 늘어나면
데이타는 아주 간단하게 저장되지만.. 쿼리가 엄청나게 길어집니다.


사실 문제갯수만큼 번호(순서) 만 바뀔 뿐 똑같은게 반복되니깐
그래서 generate_series(1,3) 을 이용하여 이래저래 해보는데..
이상하게 조인조건이 없어서인지.. cross join 된 결과가 나와버려서..
여엉 엉뚱한 답이 나옵니다.


generate_series() 를 이용하면 될것도 같은데..
잘 안 되네요...

힌트나 도움 좀 부탁합니다.


postgresql 에서도 오라클의 decode () 를 지원해 줬음 좋겠습니다.
(어떻게 안 될려나요?..)

이 글에 대한 댓글이 총 4건 있습니다.

관계형 설계에 비추어서는 잘 된 설계는 아니지만 굳이 이대로 하신다면

SETOF 키워드를 사용하는 저장프로시저를 만드는 게 좋겠는데요.

초보대왕님이 2006-11-26 22:26에 작성한 댓글입니다.
이 댓글은 2006-11-26 22:27에 마지막으로 수정되었습니다. Edit

그럼.. 어떤식의 테이블 구성이 적합할까요?


일단 나와야 할 결과물은 질문처럼 되는것과


오답인지 정답인지의 구분을 할 수 있어야 하는데..

질문처럼 하면 오답/정답 여부는 아주 쉽게 알 수 있지만....


아울러.. 문제지마다 문제수가 달라질수 있고요..

또한 문항수도 달라질수 있고요..


tyro님이 2006-11-26 23:11에 작성한 댓글입니다.
이 댓글은 2006-11-26 23:19에 마지막으로 수정되었습니다. Edit

질문에 답을 안한 경우는 어떻게 처리하셨나요?


제가 보기에는 부득이 outer joing을 써야할 것같거든요.

그렇다면, 학생수가 많아지면, 서버 부하가 커질 것같습니다. 


차라리 일반적인 RDBMS 자료설계가 더 타당해 보이기도 합니다. 


그리고, generate_series() 함수의 출발 자체가 어떤 순차적인 inline view를 만드려고 한 것이 목적인지라, 

이 문제랑은 별개의 것으로 보입니다. 


decode 문제는 case when ... then ... else ... end 구문으로 풀어가시면 될 것같네요.



시험지번호 | 학생번호 | 1번답 | 2번답 | 3 번답 ....... 예상되는 최대문항까지의 답


그리고, 

정답테이블 따로 두고, 


그리고 체점 테이블 따로 두고, 

체점 테이블에 자료가 insert 될 때 트리거를 걸어서, 

사용자 정,오답 통계테이블을 갱신하고.


전통적인 RDBMS 설계일 것같네요.


재밌겠습니다. 전혀 생각지 못했던 분야였네요. 

고민 열심히 하셔서, 참하게 움직인다면, 

그리고 대외비가 아니라면, 

자료구조 설계를 이곳에 공개해 보세요. 

꽤나 재미날 것 같습니다. 

김상기(ioseph)님이 2006-11-27 16:41에 작성한 댓글입니다.

어제까지만 해도 그렇게 안 되더니만..

다시 맘을 먹고 generate_series() 로 도전을 했습니다.


근데 의외로 쉽게 답이 나왔네요..



select no,

     sum(case q[no] when 1 then 1 else 0 end) as s1,

     sum(case q[no] when 2 then 1 else 0 end) as s2,

     sum(case q[no] when 3 then 1 else 0 end) as s3,

     sum(case q[no] when 4 then 1 else 0 end) as s4,

     sum(case q[no] when 5 then 1 else 0 end) as s5

from ans, generate_series(1,3) no

where ans.q[no] is not null 

group by no order by no



저와 비스무리하게 어젠 했는데 왜 cross join 이 되었징.... --;




답을 안한 부분은 0으로 처리합니다.

decode 를 언급한 것은

질문에도 이미 case 문을 사용했는데요.. 그것이 일일이 나열하자니 상당히(?) 귀찮더라고요..그래서.. 차기버젼에는 decode () 를 지원해줬음 하는 바램으로 적은 것이고요...



generate_series() 가 비용이 좀 들려나 몰겠네요 하지만 문제수가 100, 200 이런식은 아닐거니.. 괜찮을것도 같습니다.



음.. 일단 문제테이블 은 .. (자질구레한것은 제외하고)


문제테이블이


문제지번호 int, 문제번호 smallint, 질문 text, 선택지 text[], 정답 smallint

이런식으로 되어있고요..

답변 테이블은

문제지번호 int, 학생번호 int, 답변 smallint[] 이런 식입니다.


아직 체점은 생각안했는데.. 이것을 토대로 생각좀 해봐야 겠네요.


암튼 일단 답이 아주 간단하게 (?) 나와서 다행입니다.

tyro님이 2006-11-28 00:16에 작성한 댓글입니다. Edit
[Top]
No.
제목
작성자
작성일
조회
6915PostgreSQL 8.2 RC1 Released [1]
신기배
2006-11-29
3635
6914설치후 개발툴에서 암호변경은 가능합니까? [2]
이기자
2006-11-27
3621
6913bitmap scan 질문. [4]
백수환
2006-11-27
4281
6912generate_series 질문 드립니다. [4]
tyro
2006-11-26
4017
6911pgpool 3.1.1 감상. [4]
송효진
2006-11-24
4206
6910[질문]encoding "UTF8" [3]
삽질중
2006-11-24
10521
6909Table 단위로 백업이 가능한지요? [1]
이형규
2006-11-23
4114
Valid XHTML 1.0!
All about the DATABASE... Copyleft 1999-2024 DSN, All rights reserved.
작업시간: 0.020초, 이곳 서비스는
	PostgreSQL v16.2로 자료를 관리합니다