1. DELETE

 

DELETE FROM 테이블 WHERE 조건 ;
 

👩🏻‍💻 레코드를 삭제할 때 사용한다.

👩🏻‍💻 삭제는 항상 레코드 단위로 수행하므로 필드에 대한 지정은 없음.

👩🏻‍💻 삭제 동작은 특정 조건에 맞는 레코드를 찾아 제거하는 경우가 대부분이어서 WHERE 절이 항상 뒤따라 온다.

 

DELETE FROM tCity WHERE name = '부산';
SELECT * FROM tCity;
 

⬇️

 

📌  도시명이 '부산'인 레코드를 삭제

 

 

 

 

2. 삭제 안전 장치

 

👩🏻‍💻  삭제시 문제가 되는 부분은  1) 조건절을 빼거나 2) 잘못된 조건을 사용하는 경우

👩🏻‍💻  조회만 하는 SELECT 명령은 테이블을 변경하지 않아 실수해도 조건을 바꿔 다시 조회하면 됨.

       INSERT 명령은 테이블을 변경하지만 혹시라도 잘못 삽입했으면 다시 지우면 되어서 그다지 위험하지 않음

       하지만 잘못 내린 DELETE 명령은 즉시처리해 버림.

👩🏻‍💻  DELETE문은 특정 레코드를 삭제하기 위해 WHERE 절과 함께 사용하지만 실수로 WHERE 절을 생략해 버리면 모든 데이터가 삭제됨

 

 

📌  만일 월급이 300 초과인 직원을 삭제한다면 다음 절차대로 작업

// 1. DELETE 명령을 내리기 전에 먼저 SELECT로 삭제 대상 레코드를 고름
      SELECT * FROM tStaff WHERE salary > 300;
// 2. 조건을 맞는지 확인 후 제거
      DELETE FROM tStaff WHERE salary > 300;
 

 

 

 

3. TRUNCATE

 

TRUNCATE TABLE 테이블 ;
 

👩🏻‍💻  테이블 초기화 할 때 쓰는 명령어

👩🏻‍💻  DELETE 명령은 수십만건의 레코드를 일일이 지우게 되면 서버에 부하가 생긴다.

       ➡️ 이 경우 TRUNCATE 명령을 사용하는 것이 효율적

       ➡️ 물리적인 기억 장소를 깨끗이 비우고 임시 영역에 로그도 남기지 않아 훨씬 빠르다

 

TRUNCATE TABLE tCity;

 

🔽

 

 

 

 

 

[ 내용 참고 : IT 학원 강의 ]

 

'Database > MySQL' 카테고리의 다른 글

[MySQL] 서브쿼리 (SubQuery)  (1) 2024.02.24
[MySQL] UPDATE 문  (1) 2024.02.24
[MySQL] INSERT 문  (0) 2024.02.23
[MySQL] GROUP BY, HAVING  (0) 2024.02.23
[MySQL] 집계 함수 (aggregate function)  (0) 2024.02.23

 


 

1.  INSERT

👩🏻‍💻 새로운 레코드를 추가하는 명령

👩🏻‍💻 INSERT 문을 스크립트로 작성해 놓으면 많은 데이터를 순차적으로 입력할 수 있어서 편리

 

// 기본 형식 
INSERT INTO 테이블 (필드 목록) VALUES (값 목록)

  📌  명령어가 두 단어로 구성, INSERT는 삽입하라는 명령어이고 INTO는 삽입 대상을 명시하는 전치사

  📌  INTO 다음에 새 레코드를 삽입할 테이블 이름을 적은 후 필드 목록에 삽입할 필드의 이름을 콤마로 구분하여 나열

  📌  VALUES 절의 값 목록에는 필드에 대입할 값을 나열

 

// 서울 레코드를 삽입하는 원론적인 쿼리문 
INSERT INTO tCity (name, area, popu, metro, region) 
   VALUES ('서울', 605, 974 ,'y', '경기');

  👾  필드 목록, 값 목록 모두 5개여서 개수가 맞음

  👾  하지만 필드 목록과 값 목록이 반복되어 명령문이 길고 필드명을 일일이 순서에 맞춰 입력해야 되서 길어짐

          ➡️ 모든 필드를 선언 순서대로 삽입할 때는 필드 목록을 생략 할 수 있다.

          ➡️ 필드 목록이 없는 대신 값 목록이 완전해야 하며 순서도 반드시 지켜야 함

  👾  필드 목록을 밝히면 꼭 선언 순서에 맞추지 않아도 결과값은 순서대로 출력 된다.

 

INSERT INTO tCity VALUES ('서울',605, 974,'y','경기'); 
-- 서울이 이미 있어서 중복 삽입을 할수 없으므로 테이블에 없는 평택을 입력. 
INSERT INTO tCity VALUES ('평택', 453, 51, 'n', '경기');

 

INSERT INTO tCity VALUES ('평택', 51, 453, 'n', '경기'); 
-- area와 popu가 바뀜 
INSERT INTO tCity VALUES ('평택', 453, 'n', 51, '경기'); 
-- popu와 metro 순서가 바뀜 
INSERT INTO tCity VALUES ('평택', 453, 'n', '경기'); 
-- popu 필드값 누락 

-- 필드 목록을 밝히면 꼭 선언 순서에 맞추지 않아도 원하는 순대대로 나열할 수 있음. 
INSERT INTO tCity (area, popu, metro, region, name) 
     VALUES (453, 51, 'n', '경기', '평택');

 

 

 

2.  확장 INSERT문

👩🏻‍💻  각 행마다 개별적으로 INSERT INTO 명령을 일일이 작성하면 쿼리문이 길어 번잡스러움

       ➡️ 대량의 데이터를 삽입할 때는 VALUES 뒤에 차례로 나열하면 편하다.

👩🏻‍💻  백업을 복구하는 경우 속도는 개별보다 느리다.

👩🏻‍💻  표준SQL 문법은 아니고 오라클에서도 지원하지는 않음.

 

INSERT INTO tCity (name, area, popu, metro, region) 
  VALUES ('서울',605,974,'y','경기'), 
         ('부산',765,342,'y','경상'), 
         ('오산',42,21,'n','경기'), 
         ('청주',940,83,'n','충청'), 
         ('전주',205,65,'n','전라'), 
         ('순천',910,27,'n','전라'), 
         ('춘천',1116,27,'n','강원'), 
         ('홍천',1819,7,'n','강원');

 

 

 

3.  INSERT SELECT

// 기본형 
INSERT INTO 대상테이블 (필드목록) SELECT 필드목록 FROM 원본테이블;

👩🏻‍💻 INSERT 명령은 한번에 하나의 레코드만 삽입하지만, 다른 테이블 또는 자기 자신에게 이미 저장되어 있는 대량의 정보를 복사할 때는

조회한 결과셋을 한꺼번에 삽입할 수 있다.

👩🏻‍💻 INSERT INTO와 기본 형식은 비슷하지만 필드의 값을 VALUES 대신 SELECT 명령으로 다른 테이블에서 읽어온다는 점이 다르다.

👩🏻‍💻 다른 테이블이나 같은 테이블의 정보를 재활용하는 경우 많다.

 

INSERT INTO tStaff (name, depart, gender, joindate, grade, salary, score) 
  SELECT name, region, metro, '20210629', '신입', area, popu 
     FROM tCity WHERE region = '경기';

 

📌  tCity 테이블에서 경기도 소속의 도시 정보를 읽어 tStaff 테이블에 신입 직원으로 삽입

 

 

 

4.  CREATE SELECT

CREATE TABLE 대상테이블 AS SELECT 필드목록 FROM 원본테이블

 

👩🏻‍💻 INSERT SELECT 와 유사하되 기존 테이블에 레코드를 삽입하는 것이 아니라 새로 테이블을 만들어 결과셋을 삽입하는 점이 다르다.

👩🏻‍💻 기존 테이블의 일부 필드와 레코드를 가져와 삽입하는 명령이어서 대상 테이블이 존재하면 안된다.

👩🏻‍💻 원본을 손상시키지 않고 특수한 작업을 하기 위해 사본을 만드는 경우 유용

 

CREATE TABLE tSudo AS SELECT name, area, popu FROM tCity 
   WHERE region = '경기'; 
   
SELECT * FROM tSudo;

📌  경기도 지역의 도시만으로 tSudo 테이블을 생성

 

 

📍 tStaff 테이블에 대량의 변경을 가해야 하는데 불안할 경우 다음 명령으로 복사

CREATE TABLE tStaff_backup_240206 AS SELECT * FROM tStaff;

   📌  백업은 여러번 뜰 수 있어서 관행상 날짜를 명시.

   📌  데이터의 백업은 되나 원본 테이블의 키 속성을 가지고 오지 못한다.

[ 내용 참고 : 코딩학원 강의 ]

'Database > MySQL' 카테고리의 다른 글

[MySQL] UPDATE 문  (1) 2024.02.24
[MySQL] DELETE 문  (1) 2024.02.24
[MySQL] GROUP BY, HAVING  (0) 2024.02.23
[MySQL] 집계 함수 (aggregate function)  (0) 2024.02.23
[MySQL] SELECT문 | ORDER BY, DISTINCT, LIMIT, OFFSET FETCH  (0) 2024.02.23


 

1. GROUP BY

 

🍋 기준이 되는 필드를 뒤에 적어주면 기준 필드가 같은 레코드를 모아 통계값을 구함

🍋 GROUP BY 구문은 그룹핑을 해 줄 뿐이며 어떤 통계를 낼 것인가는 필드 목록의 집계 함수에 따라 달라짐

🍋 여러 개의 집계함수를 동시에 사용 가능

SELECT '영업부', AVG(salary) FROM tStaff WHERE depart='영업부';
SELECT '총무부', AVG(salary) FROM tStaff WHERE depart='총무부';
SELECT '인사과', AVG(salary) FROM tStaff WHERE depart='인사과';
 

📌  부서별 월급 평균을 알고 싶어 부서마다 AVG 함수를 호출하게 되면 부서 목록을 만들고 각 부서마다 명령을 일일이 실행해야 하고 결과도 따로 출력되어 보기도 불편하다. 또한, 집계함수와 일반필드를 같이 적을 수 없어 필드 목록에 부서명을 한 번 더 적어야 한다.

 

💡 이 경우에 필요한 구문이 GROUP BY. 기준 필드는 집계 함수와 같이 쓸 수 있어서 목록도 보기 좋게 출력 할 수 있음.

 

 

📌  부서별 월급 평균을 구하려면 depart 필드 기준으로 그룹핑

    1)  기준 필드순으로 정렬하여 같은 그룹끼리 구분

    2)  통계 대상 필드를 순서대로 읽어 집계를 구함

SELECT depart, AVG(salary) FROM tStaff GROUP BY depart;
SELECT grade, AVG(salary) FROM tStaff GROUP BY grade;
SELECT depart, COUNT(*), MAX(joindate), AVG(score) FROM tStaff GROUP BY depart;
 

 

 

 

2. 기준 필드

 

🍋 GROUP BY의 기준 필드는 중복 값이 있을 때만 의미있다.

     ➡️ 레코드별로 고유한 값을 가지는 필드는 그룹핑 기준으로 부적합(예 : 아이디)

     ➡️ 한 부서에서 여러 직원이 소속되어 있고 부서가 같은 직원이 많기 때문에 부서별 집계 가능.

     ➡️ 성별도 중복값이어서 그룹핑 필드로 적합

SELECT gender, AVG(salary) FROM tStaff GROUP BY gender;
 

 

 

📌  남녀 성별로 평균 월급을 구함. 성별은 남자, 여자 두 부류이며 그룹핑한 결과도 2개의 레코드로 출력

 

 

 


 

 

🔖  중복 값을 가지는 필드만 그룹핑의 기준이 되는 것은 아니며 임의의 필드를 기준으로 그룹핑 할 수 있다.

SELECT name, SUM(salary) FROM tStaff GROUP BY name;
 

 

 

 

 

 

📌 이름을 기준으로 그룹핑을 하는 것도 문법적으로 가능하지만 전 직원의 월급이 각각 출력이 되어 의미가 없음.

 

 

 

 

 

 

 


 

🔖  기준 필드를 콤마로 구분하여 두 개 이상도 쓸 수 있다.

      ➡️ 이 경우 첫 번째 기준으로 그룹을 나누고 그 그룹 내에서 다시 두 번째 기준으로 그룹을 나눈다.

🔖  기준 필드의 순서는 그룹핑 과정에 영향을 주지만 결과에는 영향을 미치지 않는다.

      ➡️ 순서는 ORDER BY로 조정 가능

SELECT depart, gender, COUNT(*) FROM tStaff GROUP BY depart, gender;
SELECT gender, depart, COUNT(*) FROM tStaff GROUP BY gender, depart;
SELECT depart, gender, COUNT(*) FROM tStaff GROUP BY depart, gender ORDER BY gender, depart;
 

 

📌 부서별, 성별로 그룹핑하여 직원수 구함.  총무부는 여직원이 없어서 5개의 그룹만 나옴.

 

 

 

3.  GROUP BY의 필드 목록

 

⚡️  <그룹핑 쿼리의 기본 형식>

SELECT 기준필드, 집계함수() FROM 테이블 GROUP BY 기준필드;
 

🍋 GROUP BY 절이 있으면 필드 목록에는 기준 필드나 집계 함수만 와야 한다.

🍋 필드 목록의 제일 처음에는 통상 기준 필드를 출력하여 어떤 그룹에 대한 통계인지 표시

      ➡️ 기준 필드를 빼고 집계 함수만으로 쿼리를 구성하면, 계산은 똑바로 됐지만 각 행이 어떤 부서에 대한 통계치인지 알아 볼 수 없다.

 

SELECT depart, salary FROM tStaff GROUP BY depart;
SELECT SUM (salary) FROM tStaff GROUP BY depart;
 

 

 

 

🍋  집계 함수는 다중 값이 있어야 계산할 수 있으므로 그룹핑을 할 때만 유용

       ➡️ GROUP BY 절 없이 일반 필드와 집계 함수를 같이 출력하면 의미가 없다

SELECT depart, SUM(salary) FROM tStaff;
 

  📌  레코드별로 고유한 부서명과 통계에 의해 계산하는 월급 총합은 같이 출력할 수 있는 값이 아니라서

        이 명령은 다음 둘 중에 하나로 수정하는게 적당.

 📌  뒤에 GROUP BY 절을 붙여 부서별로 그룹핑하면 기준 필드인 부서명도 출력할 수 있고

       부서의 월급 총합을 구하는 SUM 함수도 사용할 수 있다.

SELECT depart, SUM(salary) FROM tStaff GROUP BY depart;
SELECT SUM(salary) FROM tStaff;
 

 

 

 

4. HAVING

 

// 위치 순서
SELECT ... FROM ... WHERE ... GROUP BY ... HAVING ... ORDER BY
 

🍋 HAVING은 GROUP BY 다음에 오며 통계 결과 중 출력할 그룹의 조건을 지정 (즉 HAVING은 GROUP BY 문의 조건절)

 

  📌  부서별 평균 월급을 출력하는 명령은 별다른 조건이 없으면 모든 부서의 평균 월급을 출력.

        평균 월급이 340을 넘는 부서만 출력하고 싶다면 GROUP BY 다음에 HAVIING 절을 추가.

SELECT depart, AVG(salary) FROM tStaff GROUP BY depart HAVING AVG(salary) >= 340;
 

 

📌  그룹별 통계를 뽑고 그 결과셋에서 HAVING 조건에 맞는 레코드만 출력.

      평균 월급이 327인 인사과는 제외.

 

 

 


 

 

🍋 출력 순서를 지정할 때는 ORDER BY 절을 뒤에 붙인다.

🍋 GROUP BY 다음에 HAVING이 오고 ORDER BY는 항상 제일 마지막에 위치한다.

SELECT depart, AVG(salary) FROM tStaff 
  GROUP BY depart HAVING AVG(salary) >= 340 
    ORDER BY AVG(salary) DESC;
 

 


 

 

🍋 WHERE 와 HAVING은 적용 시점과 제한 대상이 다르다.

🍋 WHERE 절은 GROUP BY 앞에 나타나며 통계 대상 레코드의 조건을 제한한다.

SELECT depart, AVG(salary) FROM tStaff WHERE salary > 300 GROUP BY depart;
 

 

 

📌  월급 300 초과 조건에 의해 월급 300 이하의 직원은 평균에서 아예 제외되어 평균값이 더 높게 나타남. 만약 모든 직원의 월급이 300 이하이면 이 부서는 아예 결과셋에 나타나지고 않음.

 

 

 

 

🍋 HAVING 절은 GROUP BY 다음에 나타나며 집계한 결과셋의 조건을 제한한다.

SELECT depart, AVG(salary) FROM tStaff WHERE salary > 300 GROUP BY depart 
HAVING AVG(salary) >= 360 ORDER BY depart;
 

 

 

📌 월급이 300 초과인 직원들을 대상으로 부서별 평균 월급을 구하고 그 결과 평균 월급이 360 이상인 부서만 고른 후 부서명으로 정렬

 

 

⚡️ 처리순서

 

1. WHERE 절이 직원목록에서 월급 300이하의 직원을 먼저 제거

2. 부서별로 그룹핑하여 AVG 함수로 남은 직원의 부서별 평균 월급을 계산

3. HAVING 절에 의해 평균 월급이 낮은 부서는 제외

4. 남은 부서를 ORDER BY가 정렬하여 출력

 

 

 

SELECT depart, MAX(salary) FROM tStaff WHERE depart IN ('인사과', '영업부') GROUP BY depart;
SELECT depart, MAX(salary) FROM tStaff GROUP BY depart HAVING depart IN ('인사과', '영업부');
 

 

 

📌 두 쿼리 모두 인사과와 영업부의 최대 월급을 조사.

📌 조건을 적용하는 시점은 다르지만 조건의 내용은 같아 최종 실행 결과는 같음.

 

 

💡 내부적인 실행 과정은 차이가 있음

    1. WHERE 절은 집계전에 총무부를 제외하여 꼭 필요한 계산만 함.

    2. HAVING 절은 모든 부서의 집계를 다 끝낸 후 총무부를 제거하는 식이라 출력하지도 않을 총무부의 집계까지 계산하여 비효율적

 

 

 

 

 

 

[ 내용 참고 ; IT 학원 강의 ]

 

 


 

1. 집계함수 Aggregate Function

🍋  집계 함수는 복수개의 레코드에 대해 집합적인 계산을 수행하여 합계, 평균, 분산 같은 통계값을 산출.

🍋  테이블에 저장된 정보를 함수로 전달하면 원본 데이터를 변형, 가공하여 돌려준다.

🍋  함수 호출문이 하나의 값이므로 필드 목록이나 조건절등에 값처럼 사용하면 된다.

함수명
설명
COUNT()
행의 개수를 센다
AVG()
평균을 구한다
MIN()
최소값을 구한다
MAX()
최대값을 구한다
STDEV()
표준편차를 구한다
VAR_SAMP()
분산을 구한다

 


 

(1) COUNT() : 행의 개수를 센다

📍 COUNT는 개수를 조사할 필드명을 전달하는데 * 지정하면 필드에 상관없이 조건에 맞는 레코드 개수를 리턴

 

// tStaff 테이블에 저장되어 있는 레코드 개수
  SELECT COUNT(*) FROM tStaff;
// 계산값은 열 이름이 없는데 별명을 부여하면 결과셋에 이름을 표시.
  SELECT COUNT(*) AS "총 직원수" FROM tStaff;

 

 

 

 

📍 WHERE 절을 붙이면 조건에 맞는 레코드의 개수를 구한다.

SELECT COUNT(*) FROM tStaff WHERE salary >= 400; // 월급이 400 이상인 직원의 수
SELECT COUNT(*) FROM tStaff WHERE salary >= 10000; // 월급이 10000 이상인 직원의 수

 

📍 집계는 모든 레코드의 값을 참고하여 하나의 값을 구하는 것이어서 결과셋은 목록이 아닌 딱 하나의 값

       ➡️ 집계하는 말 자체가 다중값으로 부터 단일 값을 산출한다는 의미.

📍 조건에 맞는 레코드가 없어도 결과 값은 역시 하나

 

 

📍 특정 필드의 개수를 구할때는 인수로 필드명을 적는다.

      ➡️ 지정한 필드 값이 존재하는 레코드의 개수를 구함

SELECT COUNT(name) FROM tStaff; 
SELECT COUNT(depart) FROM tStaff;

 

 

 

 

📍 중복 부서를 제외하고 부서의 종류가 몇 개인지 알고 싶으면 필드명 앞에 DISTINCT 키워드를 붙인다.

SELECT COUNT(DISTINCT depart) FROM tStaff;

 

 


 

📍 COUNT 함수는 '필드값이 제대로 들어 있는 레코드의 개수만 구하며' 필드값이 NULL인 레코드는 개수에서 제외.

📍 name이나 depart는 NULL이 없어 전체 직원수와 같지만, score 필드는 NULL 값이 있음.

SELECT COUNT(score) FROM tStaff; 
SELECT COUNT(*) - COUNT(score) FROM tStaff; 
SELECT COUNT(*) FROM tStaff WHERE score IS NULL;

 

 

 

 

(2) SUM(), AVG(), MIN(), MAX()

 

SELECT SUM(popu), AVG(popu) FROM tCity; // 도시 목록에서 인구의 총합과 평균을 구함. 
SELECT MIN(area), MAX(area) FROM tCity; // 모든 도시의 area 필드를 조사하여 가장 작은 값과 가장 큰 값을 찾음.

 

 

 

 

 

📍 WHERE 절을 붙이면 조건을 만족하는 레코드에 대해서만 집계를 함

 

SELECT SUM(score), AVG(score) FROM tStaff WHERE depart = '인사과'; // 인사과의 총 실적 합계과 평균
SELECT MIN(salary), MAX(salary) FROM tStaff WHERE depart = '영업부'; // 영업부에서 가장 낮는 월급과 가장 높은 월급

 

 

 

 

📍 문자열끼리는 더할 수 없어 총합을 계산할 수 없고 평균도 의미가 없다.

📍 but! 문자열이나 날짜끼리는 사전순으로 비교할 수 있고, 날짜에 대해서는 MIN, MAX 함수 사용 가능하다.

📍 집계함수와 일반필드은 같이 사용하면 안된다.

SELECT SUM(name) FROM tStaff; 
SELECT MIN(name) FROM tStaff; 
SELECT MAX(popu), name FROM tCity; (x) 
-> SELECT popu, name FROM tCity ORDER BY popu DESC LIMIT 1;

 

 

 

(3) 집계 함수와 NULL

📍 NULL은 값을 알수 없는 특수한 상태로 모든 집계 함수는 NULL을 무시하고 통계를 계산한다.

📍 단, 예외적으로 레코드 개수를 세는 COUNT(*)는 NULL 도 포함하지만, 인수로 필드를 지정하면 NULL을 세지않는다.

SELECT AVG(salary) FROM tStaff; 
SELECT SUM(salary)/COUNT(*) FROM tStaff; // 평균은 총합을 개수로 나누어서 구함 위의 문장과 동일

 

 

 

 

📍 score의 경우에는 다른 값이 나온다.

      ➡️ AVG 함수는 NULL 값을 제외하고 계산을 하지만, COUNT(*)의 경우 NULL 값도 포함

      ➡️ 시스템 규칙에 따라 NULL이 0을 나타내는 것일 수 있음.

SELECT AVG(score) FROM tStaff; 
SELECT SUM(score)/COUNT(*) FROM tStaff; 
SELECT SUM(score)/COUNT(score) FROM tStaff;

 

 

 

 

📍 COUNT(*)는 없다는 뜻의 0을 리턴, 다른 집계함수는 계산 대상이 없어서 존재하지 않는 0이 아니라 NULL을 반환

SELECT COUNT(*) FROM tStaff WHERE depart = '비서실'; 
SELECT MIN(salary) FROM tStaff WHERE depart = '비서실';

[ 내용 참고 : IT 학원 강의 ]

 

 

 

 

1. ORDER BY

 

🐰 SELECT 명령에 필드 지정이 없을 경우 레코드의 출력 순서는 DBMS의 디폴트 순서를 따름.

🐰 관계형 DB에서 레코드의 물리적 순서는 큰 의미가 없고, 대신 출력할 때 ORDER BY 절로 정렬 순서를 원하는대로 지정.

// 기본형식
ORDER BY 필드 [ASC | DESC]
 

 

🐰 ORDER BY 다음에 정렬 기준 필드를 적고 오름차순일 경우 ASC 키워드를, 내림차순일경우 DESC 키워드를 지정.

🐰 순서를 생략하면 디폴트인 오름차순으로 적용되므로 키워드 ASC는 보통 생략.

SELECT * FROM tCity ORDER BY popu;
SELECT * FROM tCity ORDER BY popu ASC;
 
 
 
 

🔖  인구수를 기준으로 정렬하여 인구가 작은 도시부터 출력.

 

 

 

 

 

 

SELECT * FROM tCity ORDER BY popu DESC;
 
 

 

 

🔖  DESC를 붙이면 내림차순으로 정렬해서 인구가 많은 도시부터 출력.

 

 

 

 

 


 

 

🐰 두 개 이상의 기준 필드를 지정하는 경우  ➡️  첫 번째 기준 필드의 값이 같으면, 두 번째 기준 필드를 비교하여 정렬 순서를 결정.

SELECT region, name, area, popu FROM tCity ORDER BY region, name DESC;
SELECT region, name, area, popu FROM tCity ORDER BY region ASC, name DESC;
 

 

 
 

 

🔖 지역별로 정렬하되 같은 지역에 속한 도시끼리는 이름의 내림 차순으로 정렬.

🔖 ORDER BY 뒤에 기준 필드를 콤마로 구분하여 나열하되 각 기준별로 오름차순과 내림차순을 따로 지정 가능.

🔖 region은 순서를 지정하지 않았으므로 디폴트인 ASC가적용. 1차 정렬 기준인 지역이 같으면 2차 기준인 이름순으로 정렬하되 이때는 DESC 내림차순으로 정렬.

 

 

 

 

 

SELECT region, name, area, popu FROM tCity ORDER BY area ASC, name DESC;
 

 

 

 

 

 

🔖 area가 동일한 값이 없으므로 두 번째 정렬 기준인 name은 효력을 발휘하지 않음.

 

 

 

 

 

 

 

 

 

 

🐰 ORDER BY 기준은 보통 필드명으로 하지만 순서값으로도 지정 가능. 필드 순서 값은 테이블 생성시에 등록한 순서.

🐰 tCity의 경우 name이 1번, area가 2번, popu가 3번

SELECT * FROM tCity ORDER BY area;
SELECT * FROM tCity ORDER BY 2;
 
 
 
 

 

🔖  면적순으로 정렬하려면 area를 기준으로 하는 대신 2번 필드 기준으로 해도 결과는 같음

 

 

 

 

 

 

 

 

 

 

🐰 테이블에 존재하지 않은 계산값도 정렬 기준으로 사용할 수 있음.

SELECT name, popu * 10000 / area  FROM tCity  ORDER BY popu * 10000 / area;
SELECT name, popu * 10000 / area  AS tmp  FROM tCity  ORDER BY tmp;
 

 

 

 

🔖 인구수와 면적으로 계산한 인구밀도의 오름차순으로 도시를 정렬.

🔖 정렬 기준을 꼭 같이 출력할 필요는 없지만 제대로 정렬했는지 확인하기 위해 인구밀도를 같이 출력

 

 

 

 

 

 

 


 

 

🐰  레코드의 조건을 지정하는 WHERE 절과 출력 순서를 지정하는 ORDER BY 절을 동시에 사용 가능.

SELECT * FROM tCity WHERE region = '경기' ORDER BY area;
 

 

 

🔖  경기도에 있는 도시만 골라 면적별로 정렬.

      이때 ORDER BY 절은 WHERE 절보다 뒤쪽에 있어야 함.

 

 

 


 

 

2. DISTINCT

 

🐰 중복된 값을 제거할 때 DISTINCT 키워드를 붙인다.

    ex. 도시 테이블에서 region 필드만 읽어 도시가 속한 지역의 목록을 조사하고 싶은 경우 SELECT region FROM tCity; 로 작성

            ➡️  하지만 이런 경우 같은 도시가 여럿 있는 경우 중복해서 출력

            ➡️  단순히 어떤 지역이 있는지만 조사한다면 굳이 중복된 값을 반복해서 출력할 필요가 없음

            ➡️  DISTINCT 키워드를 사용하여 중복된 값 제거.

SELECT DISTINCT region FROM tCity;
SELECT DISTINCT region FROM tCity ORDER BY region;
 

 

 

 

🔖  DISTINCT 키워드로 중복 제거를 하다 보면 순서가 달라짐.

🔖  만약 중복도 제거하고 정렬도 하고 싶으면 ORDER BY절을 붙임.

 
 
 
 
 
 

 
 

🐰 DISTINCT의 반대 키워드는 ALL 이며 중복 제거 없이 모든 레코드를 출력.

🐰 ALL이 디폴트라서 굳이 지정할 필요는 없음.

SELECT ALL depart FROM tStaff;
 

 

 

 


 

 

3. LIMIT

 

// 기본 형식
SELECT .... LIMIT [건너뛸 개수], 총개수
 

🐰 LIMIT 구문으로 행수를 제한.

🐰 건너뛸 개수를 생략하면 0으로 적용하여 첫 행 부터 출력

 

SELECT * FROM tCity ORDER BY area DESC LIMIT 4;
SELECT * FROM tCity ORDER BY area DESC LIMIT 0, 4;
 

 

 

🔖  면적이 넓은 상위 4개 도시를 구하는 구문.

 

 

 

 

 

SELECT * FROM tCity ORDER BY area DESC LIMIT 2, 3;
SELECT * FROM tCity ORDER BY area DESC LIMIT 3 OFFSET 2;
 

 

 🔖  앞쪽 2개는 건너뛰고 이후 3개의 행을 구함.

 🔖  앞쪽 몇 개를 건너뛴 후 일정 개수 만큼 보여주는 이 구문은 게시물을 페이지 단위로 끊어서 출력할 때 실용적.

 

 

 

 


 

 

4. OFFSET FETCH

 

🐰  테이블의 일부 레코드만 조회하는 작업은 빈도가 높고 실용적이지만 DBMS 별로 사용하는 문법이 다름.

       ➡️ SQL 표준이 새로 OFFSET FETCH 문법을 만듦.

       ➡️ 일부분을 특정하려면 순서를 지정해야 되서 ORDER BY 문이 반드시 있어야 함.

       ➡️ 그래서 OFFSET FETCH 는 별도의 구문이 아니라 ORDER BY의 옵션

// 기본 형식
ORDER BY 기준필드 OFFSET 건너뛸 행 수 ROWS FETCH NEXT 출력할 행 수 ROWS ONLY;
 
SELECT * FROM tCity ORDER BY area DESC OFFSET 0 ROWS FETCH NEXT 4 ROWS ONLY;
SELECT * FROM tCity ORDER BY area DESC LIMIT 0, 4;
 
 

 

🔖  면적 순으로 상위 4개의 도시를 출력. 면적을 내림차순을 정렬 후 4개의 행만 읽음.

       ➡️ OFFSET을 지정하면 앞쪽 일부를 건너뛸 수 있음.

 

 

 

 

 

SELECT * FROM tCity ORDER BY areabDESC OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY;
SELECT * FROM tCity ORDER BY area DESC LIMIT 2, 3;
 
 
 
 

🔖  상위 2개를 건너 뛰고 다음 순서인 3, 4, 5위 3개의 도시를 조사.

 

 
 
 
 

 

 

🐰 WHERE 구문과 함께 사용하여 필터링을 먼저 하고 그 일부 레코드만 출력할 수 있음.

SELECT * FROM tCity WHERE metro = 'n' ORDER BY area DESC OFFSET 2 ROWS FETCH NEXT 3 ROWS ONLY;
SELECT * FROM tCity WHERE metro = 'n' ORDER BY area DESC LIMIT 2, 3;
 
 
 
 

🔖  광역시는 제외하고 순위를 매겨 3등에서 5등까지 출력.

 

 

 

 

 

 

 

 

[ 내용 출처 : IT 학원 강의 ]

 

 


 

1. 필드 비교 [ Where 절 ]

👾 WHERE 절은 읽을 레코드의 조건을 지정. ( * 필드 목록은 읽을 열을 지정하는데 비해 WHERE 절은 읽을 행을 지정 )

      ➡️  주로 필드와 특정값을 비교하는 조건문 형태로 작성한다.

👾 SELECT 명령은 조건에 맞는 레코드를 검색하는 것이 주 기능이어서 대개의 경우 WHERE 절과 함께 사용.

👾 WHERE 절은 DELETE, UPDATE 등의 명령과 함께 삭제 및 변경할 레코드를 선택할 때도 사용.

 

SELECT * FROM tCity WHERE area > 1000;
SELECT name, area  FROM tCity  WHERE  area > 1000;

 

 

📌 면적이 1000제곱킬로미터 보다 큰 도시만 검색.

📌 필드 목록에 * 대신 원하는 필드만 적으면 조건에 맞는 레코드의 지정한 필드만 표시.

📌 조건문은 필드와 상수, 변수 등을 표현식이되고 비교 대상끼리 타입이 호환되어야 함.

      ➡️  정수형을 문자열과 비교한다거나 실수형을 날짜와 비교해서는 안됨.


 

💡 조건문에 사용하는 비교 연산자

연산자
설명
A = B
같다.
WHERE name = '서울'
A > B
A가 더 크다.
WHERE area > 50
A < B
A가 더 작다.
WHERE popu < 100
A >= B
A가 B보다 크거나 같다.
WHERE popu >= 100
A <= B
A가 B보다 작거나 같다.
WHERE area <= 50
A <> B, A != B
A와 B는 다르다. 또는 같지 않다.
WHERE region <> '경기'

 


 

 

👾 숫자는 상수를 그냥 쓰지만 문자열과 날짜 상수는 항상 작은 따옴표로 감싸야 함.

👾 따옴표없이 서울이라고 하면 필드명을 의미.

 

SELECT * FROM `tCity` WHERE `name` = '서울' ( o )
SELECT * FROM tCity WHERE name = '서울' ( o )
SELECT * FROM tCity WHERE name = 서울 ( x )
SELECT * FROM tCity WHERE name = "서울" ( x )

 

 

 

👾 필드의 영문자를 비교할 때는 대소문자 주의. SQL문 자체는 대소문자를 가리지 않아 키워드나 테이블명, 필드명을 아무렇게나 적어도 상관이 없지만, 필드안에 저장된 값은 대소문자를 구분. 필드값의 대소문자 구분 여부는 DBMS에 따라, 설정에따라 다름. 어떤 DBMS를 사용하건 따옴표 내의 문자열 상수는 가급적 대소문자를 정확히적는 것이 바람직.

SELECT * FROM tCity WHERE metro = 'y' ;
SELECT * FROM tCity WHERE metro = 'Y' ;

 

실행 결과

 


 

 

2. NULL 비교

 

👾 NULL은 값이 입력되어 있지 않은 특수한 상태를 표현. 값을 알 수 없거나 아직 결정할 수 없다는 뜻이며 0이나 빈 문자열과는 다름.

👾 필드를 선언할 때 NULL 가능성을 미리 지정한다. 선언문 뒤에 NULL이 있으면 이 필드는 값을 입력하지 않아도 된다는 뜻

 

CREATE TABLE tCity (
name CHAR(10) PRIMARY KEY,
area INT NULL,
popu INT NULL,
metro CHAR(1) NOT NULL,
region CHAR(6) NOT NULL
);

 

 

  📌 인구와 면적이 NULL 가능하다고 되어 있음. 정보가 아직 조사되지 않았거나 모르는 상태일 때 이 필드를 NULL로 남겨 둠.

  📌 반면 광역시 여부나 지역은 NOT NULL로 선언 되어 있어 값이 없으면 레코드를 삽입할 수 없음.

 

 

SELECT * FROM tStaff WHERE score = NULL;       ( x )
SELECT * FROM tStaff WHERE score IS NULL;      ( o )
SELECT * FROM tStaff WHERE score IS NOT NULL;  ( o )

 

  📌 NULL 값을 검색할려고 조건절에서 = NULL 로 작성.

  📌 NULL은 값이 아니라 상태이기 때문에 = 연산자로 비교할 수 없음.

       ➡️ IS NULL 연산자를 따로 제공.

       ➡️ NULL이 아니라는 조건은 IS NOT NULL로 표기.

 

 

 


 

 

3. 논리 연산자

 

👾 두 개 이상의 조건을 동시에 검색할 때는 AND, OR 논리 연산자를 사용

👾 AND는 두 조건이 모두 참인 레코드를 검색하며 OR는 두 조건 중 하나라도 참인 레코드를 검사.

 

SELECT * FROM tCity WHERE popu >=100 AND area >= 700;

 

 

 

📌 인구 100만명 이상, 면적 700제곱킬로미터 이상인 도시를 검색하여

두 조건을 만족하는 부산만 출력.

 

 

SELECT * FROM tCity WHERE popu >=100 OR area >= 700;

 

 

 

 

📌 AND를 OR로 변경하면 두 조건중 하나라도 참인 레코드 검색.

 

 

 

 

 

 

 

👾 세 개 이상의 조건문을 지정할 때도 마찬가지로 WHERE 절을 작성하되 조건의 우선순위에 주의

👾 AND의 우선 순위가 OR 보다 높다. 애매할 경우에는 괄호로 우선 순위를 지정하는 것이 좋음.

 

SELECT * FROM tCity WHERE region = '경기' AND popu >= 50 OR area >= 500;
SELECT * FROM tCity WHERE area >= 500 OR region = '경기' AND popu >= 50 ;

 

 

 

 

📌 경기권 도시중 인구 50만이상이거나 또는 경기권이 아니고 인구가 50만보다 적더라도 면적이 500 이상인 도시를 검색

 

 

 

SELECT * FROM tCity WHERE region = '경기' AND (popu >= 50 OR area >= 500);

 

 

📌 인구가 50만이 넘거나 면적이 500이상인 경기도 도시를 검색.

 

 


👾 NOT 연산자는 표현식의 진위 여부를 반대로 바꿈. 즉 뒤의 표현식이 참이면 거짓으로 바꾸고 거짓이면 참으로 바꾸어 반대 조건을 취함.

SELECT * FROM tCity WHERE region != '경기';
SELECT * FROM tCity WHERE NOT (region = '경기');

 

 

 

 

📌 경기도 소속이 아닌 도시의 정보를 조사. 복합 조건의 반대를 취할때는 NOT이 편리.

 

 

 

 

 

SELECT * FROM tCity WHERE region = '전라' OR metro = 'y'; // 전라도에 있거나 광역시인 도시
SELECT * FROM tCity WHERE region != '전라' AND metro != 'y'; // 위의 조건의 반대
SELECT * FROM tCity WHERE NOT(region = '전라' OR metro ='y');

 

 

📌 A AND B의 부정은 !A OR !B 이며 이를 모르간의 법칙

 


 

 

4. LIKE

 

👾 '=' 비교 연산자를 완전히 일치하는 조건식을 표현하는데 비해 LIKE 연산자는 패턴으로 '부분 문자열'을 검색.

ex. 성이 김씨인 사람, 주소가 강남구인 사람들을 검색할 때 편리

 

⚡️ LIKE 문의 패턴에 사용하는 와일드 카드 ⚡️

 
문자
설명
%
복수 개의 문자와 대응. %자리에는 임의 개수의 임의 문자가 올 수 있음
_
하나의 문자와 대응 _자리에는 하나의 임의 문자가 올수 있음
[]
[]안에 포함된 문자 리스트 중 하나의 문자와 대응
[^]
[^]안에 포함된 문자 리스트에 포함되지 않은 하나의 문자와 대응

👾 임의 개수의 임의 문자와 대응하는 % 와일드 카드를 주로 사용한다.

 

SELECT * FROM tCity WHERE name LIKE '%천%';

 

 

 

📌  이름에 "천"자가 들어가는 도시를 검색

 

 

 

SELECT * FROM tCity WHERE name LIKE '천%';

 

 

📌  "천"으로 시작하는 도시를 검색

 

 

 

SELECT * FROM tCity WHERE name LIKE '%천';

 

 
📌  "천"으로 끝나는 도시를 검색.

📌  '%천'의 경우 처리하는 DBMS나 타입별로 차이가 있음.

📌  공백 제거를 위해 아래와 같이 작성하기도 함.

      SELECT * FROM tCity WHERE TRIM(name) LIKE '%천' ;

 

 


 

 

5. BETWEEN

 

👾 BETWEEN A AND B 문은 "BETWEEN 최소값 AND 최대값" 형식으로 두 값 사이의 범위를 제한

👾 BETWEEN ~ AND 문은 작은 값, 큰 값 순이 상식적이어서 실수할 위험이 낮으며 구문 전체가 하나의 조건이어서 가독성이 높음.

👾 이상, 이하의 범위만 가능하며 미만, 초과는 지정할 수 없는 활용성의 한계가 있음.

👾 문자열이나 날짜에도 사용 가능. ( * 문자열은 사전순으로 비교 )

 

SELECT * FROM tCity WHERE popu BETWEEN 50 AND 100;
SELECT * FROM tCity WHERE popu >= 50 AND popu <= 100;

 

 

 

📌 인구가 50 ~ 100만 사이의 도시를 구함.

📌 "~ 보다 크고 ~ 보다 작다" 조건의 조합이어서 AND 논리 연산자로 대체 가능

 

 

 

SELECT * FROM tStaff WHERE name BETWEEN '가' AND '사';

 

 
SELECT * FROM tStaff WHERE joindate BETWEEN '20150101' AND '20180101';

 

 

 


 

 

 

6. IN

 

👾 BETWEEN 연산자는 연속된 범위만 검색할 수 있으며 불연속적이고 임의적인 값 여러 개를 조사하기 어려움.

👾 이에 비해 IN 연산자는 불연속적인 값 여러 개의 목록을 제공하여 이 목록과 일치하는 레코드를 검색.

👾 IN 연산자 뒤의 괄호 안에 콤마로 구분된 값 목록을 나열하여 이 중 하나에 해당하는지 점검.

👾 값 개수에는 제한이 없다.

 

SELECT * FROM tCity WHERE region IN ('경상','전라');
SELECT * FROM tCity WHERE region = '경상' OR region = '전라';

 

 

📌  region 필드가 '경상' 또는 '전라'인 모든 도시를 조사.

📌  IN 연산자는 여러 값 중 하나라도 해당하는지 점검하므로 각각의 비교문을 OR 논리 연산자로 연결하여 표현가능.

 

 

 

 

👾  값 리스트가 많은 경우 일일히 OR 연산자로 조건을 연결하는 것보다 IN 연산자로 값만 나열하는 것이 짧고 읽기 쉬움.

      추후 값 리스트를 편집하기도 편해 관리상의 이점이 있음.

👾  IN 연산자의 반대 조건은 NOT IN

 

SELECT * FROM tCity WHERE region NOT IN ('경상','전라');

 

 

 

📌  경상도와 전라도에 있지 않은 도시 목록을 조사

 

 

 

 

 

 

👾  부분 문자열 여러 개 중 하나에 해당하는지 찾으려면 LIKE와 IN 연산자를 같이 써야 하지만 SQL 표준에서 지원하지 않음.

      ➡️  즉 LIKE와 IN 연산자는 같이 사용할 수 없음. 이런 검색을 하고 싶으면 각각의 LIKE 조건을 OR 연산자로 연결

 

SELECT * FROM tStaff WHERE name LIKE IN ('이%', '안%'); ( x )
SELECT * FROM tStaff WHERE name LIKE '이%' OR name LIKE '안%';

 

 

 

 

📌  직원 목록에서 이씨와 안씨를 찾음

 

 

 

 

 

 

 

 

[ 내용 출처 ; IT 학원 강의 ]

+ Recent posts