고수님들 새해부터 쿼리 도움 좀 요청드리겠습니다. 0 17 973

by woni_rang [SQL Query] [2018.01.02 14:55:20]


새해 복 많이 받으시구요. 올한해 건강들 하세요.

다름 아니라 화면을 하나 만들어야하는데 쿼리가 좀 애매해서 도움 부탁드리려고 합니다.

아래는 제가 정리를 좀 해본 내용인데요. 읽어봐주시기 바랍니다.

기준 구분 항목1 항목2 항목3  
10 7 8 6 <- DB 저장값
10 8 8 7 <- DB 저장값
30        
30        
50 49 50 51 <- DB 저장값
50        
70        
70        
100        
100        

 

전값은 : 사번, 이름을 키로 등록일이 최초인 날짜의 데이터를 고정으로 조회해옵니다.
후값은 : 사번, 이름과 또 다른 키로 조회해옵니다.

1. 저장은 후값만 저장이 될것이며 항목에 값이 있는 것만 기준값과 키값(사번, 이름, 문서번호 등)들과 함께 저장이됩니다.
2. 근데 문제는 조회해올때 위 화면과 같이 저장이 저장이 안된 기준값 10~100까지 전후 다 가져와서 화면에 보여줘야합니다.
   값이 있으면 값을 보여주면 되고 없으면 없는대로 빈칸으로 보여줘야합니다.
3. 화면이 grid라서 목록형식으로 불러와야합니다.

나름 정리한다고 했는데...이해가 되실지 모르겠습니다
궁금한 점 질문해주시고 도움 부탁드리겠습니다(__)

by 우리집아찌 [2018.01.02 15:01:08]

원본 데이터 샘플 좀 올려주세요.

출력 데이터 형식은 위와 같은가요?


by woni_rang [2018.01.02 15:15:16]

아직 테이블 생성 전이라 데이터는 없구요..
위 예제 화면으로 데이터가 들어가 있다는 걸 가정한다면

emp_num emp_nam doc_no cal op1 op2 op3 create_dt update_dt
111111 아무개 14000 10 7 8 6 2017-12-31 sysdate
222222 김철수 14001 10 8 8 7 2018-01-02 sysdate
333333 이영희 14000 50 49 50 51 2017-12-31 sysdate

이 정도 데이터가 되겠네요...
음..화면에서 파라미터 넘길 때 현재 문서번호만 넘기기 때문에 후값은 사번, 이름, 문서번호로 조회하고
전값 조회할때는 문서번호로 하지 않고 사번, 이름, 등록일로 최초 전값만 조회해야합니다.

아 그리고 날짜는 Date 형식이고 나머지는 varchar2로 만들 예정입니다.


by 우리집아찌 [2018.01.02 15:33:22]

위의 데이터에서 PK는 무엇인가요?

전체 리스트중 전부 조회해서 가져오는건지...

전값을 가져오는 기준(사번,이름,등록일)이 모호합니다. 중복되는경우 어떤걸 가져와야할지

후값은 다른키라고 하셨는데... 어떤것이 기준이지 알려주셔야합니다.

기준의 10~100은 이미 정의 되어있는건지도 써주세요.

설명하신 내용으로는 이해되지 않습니다.


by woni_rang [2018.01.02 15:53:07]

네 우선 기준은 10, 30, 50, 70, 100 고정이고 PK는 사번, 이름, 문서번호 입니다.
화면에서 넘겨주는 파라미터는 사번, 이름, 문서번호 이고
전값은 사번, 이름으로 조회해서 등록일이 최초인 데이터이고
후값은 사번, 이름, 문서번호로 조회한 데이터입니다.


by 우리집아찌 [2018.01.02 16:38:11]

pk 잘못되어있는것 같네요.

사번,문서번호,cal 이렇게 되야할것 같은데요.

사번,문서번호가 pk이면 같은 사번과 문서번호가 두개이상 나올수 없습니다.

파라미터가 사번,이름 문서번호면 row가 하나만 조회되겠죠.

그리고 "전"이란건 grid 포맷에서 맨처음 한번만 나오는건가요?

 


by 마농 [2018.01.02 16:02:19]

PK 설정이 잘못된게 아닐까요?
 - 사번이 같은데 이름이 다를 수 있나요?
 - 문서번호 하나에 사번이 여러개 일 수 있나요?
cal 은 어떤 의미의 컬럼인가요?
해당 테이블은 어떤 의미의 테이블인가요?
테이블 정규화가 안된 느낌입니다.


by woni_rang [2018.01.02 16:42:35]

cal이 기준값 컬럼이구요.
문서번호 하나에 기준값 10, 30, 50, 70, 100까지 총 5row까지 저장이 됩니다.
해당 테이블은 기준값을 기준으로 획득한 점수를 저장하는 테이블입니다.

저장되는 기준값도 있고 안해도 되는 기준값도 있고한데
조회해올때는 없어도 기준값까지는 보여줘야하니 
좋은 방법이 생각나지 않아서 조언을 받게 되었습니다.


by 마농 [2018.01.02 16:50:40]

문서번호 하나에 사번이 여러개 일 수 있나요?


by woni_rang [2018.01.02 17:21:16]

한 row에 사번이 여러개 들어가지는 않습니다.
접속해서 작성하는 사람의 사번이 저장이 되는거라


문서번호1 / 접속사번1 / 기준값10
문서번호1 / 접속사번1 / 기준값30
이런식으로는 들어갈수 있습니다.


by 마농 [2018.01.02 17:32:50]

PK 는 (문서번호 + 기준코드) 입니다.
문서 하나에 기준코드 5개가 한번에 등록된다면?
문서정보 따로, 기준코드별 정보값 따로 테이블을 분리하는게 좋습니다.
필요 테이블
1. 사원 (emp_num) emp_nam
2. 문서등록 (doc_no) create_dt, update_dt, emp_num
3. 문서상세 (doc_no, cal) op1, op2, op3
4. 기준코드 (cal) cal_nam


by woni_rang [2018.01.02 19:44:40]

1. 사원 기준 테이블 기존에 존재합니다.
2.3 번은 꼭 나눠야 할까요? 마농님이니까 이유야 당연히 있겠지만 가능하다면 2.3번은 합칠수 있으면 좋겠네요.
4. 기준코드는 따로 만들면 좋겠네요.

항상하던 업무만 하다보니 깊게 못들어가는게 사실이네요.
기준코드만 따로 관리해도 저장하던 안하던 다 불러올수 있어서 좋은 방법이네요.


by 마농 [2018.01.03 08:51:55]

PK 는 (doc_no, cal) 로 하시고
별도 인덱스 (emp_num, create_dt) 가 필요합니다.
 

WITH data_t(emp_num, doc_no, cal, op1, op2, op3, create_dt) AS
(
SELECT 111111, 13000, 10,  1,  2,  3, '2017-11-31' FROM dual
UNION ALL SELECT 111111, 14000, 10,  7,  8,  6, '2017-12-31' FROM dual
UNION ALL SELECT 222222, 14001, 10,  8,  8,  7, '2018-01-02' FROM dual
UNION ALL SELECT 111111, 14000, 50, 49, 50, 51, '2017-12-31' FROM dual
)
, code_t AS
(
SELECT 10 cal FROM dual
UNION ALL SELECT  30 FROM dual
UNION ALL SELECT  50 FROM dual
UNION ALL SELECT  70 FROM dual
UNION ALL SELECT 100 FROM dual
)
SELECT a.cal
     , b.gb
     , b.op1, b.op2, b.op3
  FROM code_t a
  LEFT OUTER JOIN
       (SELECT *
          FROM (SELECT cal
                     , ROW_NUMBER() OVER(PARTITION BY cal ORDER BY create_dt) gb
                     , op1, op2, op3
                  FROM data_t
                 WHERE emp_num = 111111
                )
         WHERE gb = 1
         UNION ALL
        SELECT cal
             , 2 gb
             , op1, op2, op3
          FROM data_t
         WHERE doc_no = 14000
        ) b
 PARTITION BY (b.gb)
   ON a.cal = b.cal
 ORDER BY a.cal, b.gb
;

 


by woni_rang [2018.01.03 09:53:27]

우선 감사 말씀 드립니다.(__)

테이블 만들고 화면 만들고 하면 몇일뒤에야 쿼리를 적용할수 있겠네요.
만들어주신 쿼리로 확인해보았는데 
한가지 제 설명이 부족했었는지... 전값을 보여줄때 최초 날짜가 2017-11-31이면
2017-11-31거만 보여주는것입니다. 
현재 쿼리는 각 기준값에 최초 날짜인 것을 가져오는것 같습니다.

그래도 감사합니다.!!


by 마농 [2018.01.03 10:13:25]
WITH data_t(emp_num, doc_no, cal, op1, op2, op3, create_dt) AS
(
SELECT 111111, 13000, 10,  1,  2,  3, '2017-11-31' FROM dual
UNION ALL SELECT 111111, 14000, 10,  7,  8,  6, '2017-12-31' FROM dual
UNION ALL SELECT 222222, 14001, 10,  8,  8,  7, '2018-01-02' FROM dual
UNION ALL SELECT 111111, 14000, 50, 49, 50, 51, '2017-12-31' FROM dual
UNION ALL SELECT 111111, 13000, 30,  3,  4,  5, '2017-11-31' FROM dual
)
, code_t AS
(
SELECT 10 cal FROM dual
UNION ALL SELECT  30 FROM dual
UNION ALL SELECT  50 FROM dual
UNION ALL SELECT  70 FROM dual
UNION ALL SELECT 100 FROM dual
)
SELECT a.cal
     , b.gb
     , b.op1, b.op2, b.op3
  FROM code_t a
  LEFT OUTER JOIN
       (SELECT *
          FROM (SELECT cal
                     , RANK() OVER(ORDER BY create_dt) gb  -- 수정
                     , op1, op2, op3
                  FROM data_t
                 WHERE emp_num = 111111
                )
         WHERE gb = 1
         UNION ALL
        SELECT cal
             , 2 gb
             , op1, op2, op3
          FROM data_t
         WHERE doc_no = 14000
        ) b
 PARTITION BY (b.gb)
   ON a.cal = b.cal
 ORDER BY a.cal, b.gb
;

 


by woni_rang [2018.01.03 10:44:22]

어우...감사합니다. 어떻게 감사를 드려야할지..(__)..ㅜㅜ

그리고 실례가 안된다면..하나만 더 여쭤봐도 될까요?
join을 찾아보니 ANSI표준이라고 하던데 그걸 사용하셨는데
특별한 이유라도 있으신지..(+) 이걸로만 사용하던터라..
차이점이라도 간단히 알수 있을까요?

번거롭게 해서 죄송합니다.~


by 마농 [2018.01.03 11:42:18]

ANSI 라서 사용한게 아니라
PARTITION OUTER JOIN 은 그거밖에 안되요.


by woni_rang [2018.01.03 11:55:12]

답변 감사합니다~

댓글등록
SQL문을 포맷에 맞게(깔끔하게) 등록하려면 code() 버튼을 클릭하여 작성 하시면 됩니다.
로그인 사용자만 댓글을 작성 할 수 있습니다. 로그인, 회원가입