한 테이블 내의 두 개의 다른 행을 연결하는 조인 연산
만약에 null이 포함된 칼럼을 기준으로 count를 실행 할 경우 count는 null을 제외하고 샌다.
이를 피하고 싶다면 notnull인 항목을 기준으로 count를 해주던가 count(1)을 하는 방법도 있다.
위의 사항을 몰라서 실수한 사항이 있어서 적어둔다.
문제 - 부서별 전체 사원수와 커미션을 받는 사원들의 수를 구하는 쿼리
내 풀이
SELECT COUNT(1) AS '전체 사원수', emp.DEPTNO, COALESCE(COMM_COUNT, 0) '커미션 사원수'
FROM emp LEFT OUTER JOIN
(SELECT COUNT(1) AS COMM_COUNT, DEPTNO
FROM emp
WHERE COMM IS NOT NULL
AND COMM <> 0) emp2
ON emp.deptno = emp2.deptno
GROUP BY emp.DEPTNO;
강사님 풀이
SELECT deptno, COUNT(*), COUNT(IF((comm = 0), NULL, comm))
FROM emp
GROUP BY deptno
IF와 COUNT에 대한 사항을 알고 있었으면 쉽게 풀렸을 사항 인데, 해당 사항을 인지하지 못해서 너무 복잡한 답이 되었다.
from 에서 참조하는 테이블은 스칼라 서브쿼리에서 이용할 수 있으니 기억해두자. (아래 코드의 e.deptno처럼)
SELECT e.ename, (SELECT dname FROM dept WHERE deptno=e.deptno)
FROM emp e
WHERE e.ename = 'JONES'
인라인 뷰 - from에서 사용하는 서브쿼리
스칼라 서브쿼리 - select에서 사용하는 서브쿼리. 결과는 행 하나.
구현코드
System.out.println("==회원가입==");
boolean isExistsMember = true;
boolean isEqualPass = false;
String loginId = "";
String password = "";
String passCheck = "";
String name = "";
SecSql insertMemberSql = new SecSql();
SecSql exsitsMemberSql;
while (isExistsMember) {
System.out.print("로그인 id >");
loginId = sc.nextLine();
if (isEmpty(loginId)) {
System.out.println("login ID는 필수 입력 사항입니다.");
continue;
}
boolean isVallCheckOk = Pattern.matches("^[a-z0-9-_]{5,20}$", loginId);
if (!isVallCheckOk) {
System.out.println("5~20자의 영문 소문자, 숫자와 특수기호(_),(-)만 사용 가능합니다.");
continue;
}
exsitsMemberSql = new SecSql();
exsitsMemberSql.append("SELECT COUNT(1) FROM `MEMBER` WHERE loginId = ?", loginId);
isExistsMember = DBUtil.selectRowIntValue(conn, exsitsMemberSql) != 0;
if (isExistsMember) {
System.out.println(loginId + "는 이미 존재합니다.");
}
}
while (!isEqualPass) {
System.out.print("비밀번호 >");
password = sc.nextLine();
if (isEmpty(password)) {
System.out.println("login ID는 필수 입력 사항입니다.");
continue;
}
boolean isVallCheckOk = Pattern.matches("^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,16}$",
password);
if (!isVallCheckOk) {
System.out.println("비번은 8~16자로 영문 대문자/소문자, 숫자, 특수문자(!@#$%^*+=-)를 조합하여 사용하여 사용해 주세요.");
continue;
}
// "8~16자로 영문 대문자/소문자, 숫자, 특수문자(!@#$%^*+=-)를 조합하여 사용하여 사용해 주세요."
isVallCheckOk = false;
while (!isVallCheckOk) {
System.out.print("비밀번호 확인 >");
passCheck = sc.nextLine();
isVallCheckOk = Pattern.matches("^(?=.*[a-zA-Z])(?=.*[!@#$%^*+=-])(?=.*[0-9]).{8,16}$",
passCheck);
if (!isVallCheckOk) {
System.out.println("비번은 8~16자로 영문 대문자/소문자, 숫자, 특수문자(!@#$%^*+=-)를 조합하여 사용하여 사용해 주세요.");
continue;
}
}
isEqualPass = password.equals(passCheck);
if (!isEqualPass) {
System.out.println("비밀번호와 비밀번호 확인이 일치하지 않습니다.");
}
}
while (true) {
System.out.print("이름 >");
name = sc.nextLine().trim();
if (!isEmpty(name)) {
break;
}
System.out.println("이름는 필수 입력 사항입니다.");
}
insertMemberSql.append("INSERT INTO `MEMBER`");
insertMemberSql.append("SET regDate = NOW(),");
insertMemberSql.append("updateDate = NOW(),");
insertMemberSql.append("loginId = ?,", loginId);
insertMemberSql.append("loginPw= ?,", password);
insertMemberSql.append("`name`= ?", name);
int id = DBUtil.insert(conn, insertMemberSql);
System.out.println(id + "번 회원이 등록되었습니다.");
개선점.
DBUtil안에 얻어온 값이 1인가 아닌가를 체크해서 boolean타입으로 실행하는 메소드가 있다.
그걸 활용하면 코드를 조금 더 줄일 수 있다.
mySql에서는 TRUE 와 FALSE를 숫자 1과 0으로 표현하니 이점도 참고하자.