오라클 SQL 질문입니다. 특정값을 포함하지 않은 그룹화 해서 찾으려고 하는데 막히네요 0 8 1,918

by 피리부 [SQL Query] SQL 그룹 [2022.08.18 15:14:35]


회원 정보 조회를 하는데 

회원의 ID 값을 ID  그리고 회원의 정보 변경시 ID에 SERIAL 값으로 001 ,002 이런식으로 저장합니다. 

그리고 상태값은 STATUS 로 1 값은 등록중 , 2 전데이터, 3 정보변경전 자료, 4 해지 

이런식으로 구분해서 사용하고있으며, 주민번호, 이름, 휴대폰번호, 그리고 등록기간 ,등등의 데이터가 있습니다.

 

 그런데 상태값이 그 해당 회원이 1 즉 등록중이 하나도 없는 3번값만 있는 회원 정보를 찾으려고 하는데 막혀서 진행이 되지않습니다.

 

 SELECT STATUS, 주민번호, 이름, 핸드폰 번호, 등록만료일 FROM 회원정보

 WHERE 등록만료일 > 오늘날짜 AND STATUS !='1' AND STATUS = '3'

 

으로 처음 시도했는데 당연히 3인값만 나오네요.

 

 그룹화해서 해결해야하나 해서 시리얼값을 빼고 그룹화해서 찾아보려고 하다가 ... 자꾸 벗어나고 이상한 값만 나와서 조언을 청합니다. 

by 마농 [2022.08.18 16:04:51]
SELECT STATUS, 주민번호, 이름, 핸드폰 번호, 등록만료일
  FROM 회원정보 a
 WHERE 등록만료일 > 오늘날짜
   AND STATUS = '3'
   AND NOT EXISTS (SELECT 1
                     FROM 회원정보
                    WHERE 등록만료일 > 오늘날짜
                      AND STATUS = '1'
                      AND ID = a.ID
                   )
;

 


by 피리부 [2022.08.19 09:26:31]

답변 감사합니다~ 제가 질문 자체를 미흡하게 해서 원하던 결과가 나오진 않았네요 ㅎㅎ 

 저기서 벗어나는 값이 너무 많아서 알려주신 쿼리를 바탕으로 찾아보고 공부해서 해결해보아야겠네요 ! 

 등록만료일이 남아 있지만 해지하거나, 양도한 데이터들이 있는걸 생각하지못했네요 

 

 감사합니다!


by 창조의날개 [2022.08.18 16:41:33]

회원의 ID 값을 ID  그리고 회원의 정보 변경시 ID에 SERIAL 값으로 001 ,002 이런식으로 저장하면 문제가 있지 않나요?

 

예를 들어 홍길동이라는 사람이 등록중이면 ID가 001이면서 STATUS가 1인 데이터가 하나 생성되고

홍길동이 정보를 변경하면 ID가 002이면서 STATUS가 3인 데이터가 만들어질텐데

그럼 홍길동이라는 사람은 데이터를 변경할때 마다 데이터가 추가 되나요?

 

만약 홍길동은 ID가 001이라면 처음에 등록중일때는 STATUS가 1 이었다가

등록이 완료되면 STATUS를 3으로 UPDATE해주는게 아닐까요?

그래야 홍길동의 ID는 001 하나만 존재 하겠죠

홍길동은 ID가 여러개 있으면 어느걸 기준으로 홍길동 데이터라고 보나요?

ID가 가장 큰 값을 최종 데이터로 보고 홍길동 데이터로 보나요?

 

이건 홍길동 마스터 데이터와 이력 데이터를 하나의 테이블에서 관리 하고 있어서 생기는 문제 같습니다.

 

그래서 홍길동이라는 유일한 사람의 데이터만 모아보기 위해서 그룹화를 한다면 무엇을 기준으로 해야 하는지요?

주민번호, 전화번호, 이름 등이 있을수 있겠지만 이건 데이터 적으로 좋지 않습니다.

모두 중복이 발생할 수 있기 때문이죠(주민번호는 유일하다고 볼수도 있지만 요즘은 개인정보로 주민번호를 저장하기 어려운 문제와 2000년 이후 출생자는 없지만 그 이전 출생자중에는 중복된 데이터도 존재합니다.)

 

그리고 모든 회원이 등록중이라는 STATUS가 항상 존재하는건 아닌가보죠?

 

뭔가 설명이 부족하거나 설계 자체에 문제가 있는 것 같습니다.

 


by 피리부 [2022.08.19 09:21:06]

설명이 부족 했던것같습니다.

다르게 설명하려고 하니 ...

계약번호 / 계약시리얼 / 차량번호 / 이름 / 상태 / 계약 시작일 / 계약만료일 / 금액 / 주민번호 / 휴대폰 번호 등등 많습니다. 주민번호도 앞자리로만 해서 꼬이는것같군요 .. 

 

 계약번호는 1년 단위로 바뀌며, 상태값에 현 사용중인 계약서 는 1 , 해지된 계약서는 4, 변경된 계약서 즉 변경이 전 계약서는 3번으로 주고, 계약이 새로 1년마다 갱신된 현재 사용중인 계약서가 아닌것은 2번 으로 줍니다.

 그리고 변경된 계약서는 변경전 데이터도 필요해서 초기 000 에서 , 변경시 기존에 상태값이 1이던 계약서가 3번으로 변경되며 , 변경 완료된 계약서는 1번 값으로 시리얼 001인 계약서로 생성됩니다. 

 update가 아닌 insert 로 추가하고, 기존 값은 상태값만 변경해서 데이터를 저장해두게 됩니다. 

 그래서 해당 차량번호를 검색하면 이전에 등록했거나 변경된 계약서 및 전 계약서 그리고 지금 현재의 계약서들이 주르륵 나오게 됩니다. 

그래서 id가 여러개가 있으면 시리얼의 마지막 이 가장위로 올라가게 되어 홍길동의 데이터로 가지게 됩니다.

 이건 계약서에 저장되는 데이터이고,  따로 회원 정보나 주소 등은 다른 테이블에서 관리하고있습니다.

 

 필요한 경유 조인 등으로 불러오기도 하고 있습니다. 

 그리고 모든 회원이 등록중 이라는 상태값이 해지해서 나갈경우 등록중이 없어지기도 하고 , 계약을 갱신하지않으면 등록중의 값을 가지고 있지않습니다.

 

 지금 찾으려는 값은 누군가 데이터를 수정하는 과정에서 하나는 등록중으로 나와야하는데 , 실제로 등록중임에도 불구하고 3의 값으로 저장해서 그러한 데이터를 찾으려고 하다보니

 

 계약만료일이 남아있고, 등록중이라는 값도 없지만, 해지한 사람의 값도 제외해야해서 난항을 겪고있습니다..

 


by 창조의날개 [2022.08.19 09:31:00]

그럼 마농님께서 작성하신 쿼리에서 ID대신 계약번호를 사용하면 되겠네요

등록중이라는 데이터는 계약만료일 이전 데이터가 될 수 있겠네요.

그럼 NOT EXISTS 구문안에서는 등록만료일 조건이 필요 없겠네요.

SELECT STATUS, 주민번호, 이름, 핸드폰 번호, 등록만료일
  FROM 회원정보 a
 WHERE 등록만료일 > 오늘날짜
   AND STATUS = '3'
   AND NOT EXISTS (SELECT 1
                     FROM 회원정보
                    WHERE STATUS = '1'
                      AND 계약번호 = a.계약번호
                   )
;

단 계약번호가 달라졌을 경우 원하시는 데이터를 얻을 수 없습니다.

계약번호가 달라졌을때도 확인하고 싶다면 계약번호가 달라도 같은 계약으로 봐야하는 기준이 되는 컬럼이 있어야 합니다.

설명글에 보면 회원 정보와 조인은 한다고 하셨으니 회원번호 같은것을 이용 할 수 있겠네요.


by 마농 [2022.08.19 10:03:57]

검색조건인 "차량번호"로 조인해야 할 듯 하네요.
   AND 차량번호 = a.차량번호


by 창조의날개 [2022.08.19 09:39:13]

이런 모든 문제의 원인은 계약서 테이블에 이력데이터를 함께 저장하기 때문입니다.

만약 계약서 테이블에 최종 데이터만 저장하고 계약서이력 테이블을 만든다면 이런 문제들이 사라질 것입니다.

 

계약서 테이블에서 계약시리얼 컬럼을 삭제하여 최종 데이터만 저장하고

계약서이력 테이블에는 현재계약서 테이블에서 계약시리얼 대신 이력일시를 넣는다면 

최종 데이터는 계약서 테이블에서 조회 하고 이력은 이력테이블에서 조회하면 쉬워 집니다.

이력 테이블에는 최종 값도 함께 저장해서 현재계약서테이블과 같은 데이터가 들어 갈수 있습니다.

이렇게 하면 계약서 테입블이 최종 하나나의 데이터만 가지고 있기 때문에 목록으로 조회시 속도적인 이익도 볼 수 있습니다.

 


by 피리부 [2022.08.19 10:22:59]

그렇군요 테이블 분리도 고려해서 개편해보겠습니다 .감사합니다.!

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