1. SQL 학습을 위한 데이터베이스 구조
1.1 마당서점 시스템
마당서점 시스템은 도서, 고객, 주문 정보를 데이터베이스에 저장하여 관리한다. 운영자와 고객은 응용 프로그램을 통해 데이터를 조회하거나 처리하고, DBMS는 저장된 데이터와 접근 권한을 관리한다.
실습에서 사용하는 주요 테이블은 다음과 같다. 강의자료의 제목에는 Order라는 표현도 나오지만, 예제 SQL과 데이터 구조에 맞춰 실제 쿼리에서는 Orders를 사용한다.
| Book | 도서 정보 저장 | bookid, bookname, publisher, price |
| Customer | 고객 정보 저장 | custid, name, address, phone |
| Orders | 주문 정보 저장 | orderid, custid, bookid, saleprice, orderdate |
- Book.bookid: 도서번호
- Book.bookname: 도서이름
- Book.publisher: 출판사
- Book.price: 도서의 가격
- Customer.custid: 고객번호
- Orders.orderid: 주문번호
- Orders.custid: 주문한 고객의 번호
- Orders.bookid: 주문한 도서의 번호
- Orders.saleprice: 실제 판매가격
- Orders.orderdate: 주문일자
Book.price와 Orders.saleprice는 구분해야 한다. 전자는 도서 정보에 등록된 가격이고, 후자는 주문에 기록된 실제 판매가격이다. 총판매액은 Orders.saleprice를 이용하여 계산한다.
1.2 실습 환경과 기본 명령어
강의자료는 MySQL 8.0 이상을 기준으로 하며, HeidiSQL 또는 MySQL Workbench를 이용한다. SQL 클라이언트에서 샘플 스크립트 demo_madang.sql을 실행하여 실습 데이터베이스와 데이터를 준비한다. 접속 계정과 비밀번호는 실제 설치 환경의 설정을 사용한다.
-- 서버에 존재하는 데이터베이스 목록 확인
SHOW DATABASES;
-- 실습 데이터베이스 선택
USE madangdb;
-- 선택한 데이터베이스의 테이블 목록 확인
SHOW TABLES;
-- 각 테이블의 컬럼 구조 확인
DESC Book;
DESC Customer;
DESC Orders;
USE는 이후 SQL을 실행할 기본 데이터베이스를 선택하는 명령이다. DESC는 컬럼 이름, 자료형, NULL 허용 여부, 키 정보 등을 확인할 때 사용한다.
2. SQL의 개념과 분류
2.1 SQL이란?
SQL은 Structured Query Language의 약자로, 관계 데이터베이스에서 데이터를 정의하고 조회·조작하며 접근 권한을 관리하는 언어이다. SYSTEM R의 질의 언어인 SEQUEL에서 유래하였으며, ANSI와 ISO의 표준화 과정을 거쳤다.
SQL은 비절차적 언어이다. 사용자가 원하는 데이터와 조건을 명시하면, DBMS가 데이터를 찾고 처리하는 실행 방법을 결정한다.
예를 들어 다음 SQL은 가격이 10,000원 이상인 도서의 이름과 출판사를 요청한다.
SELECT bookname, publisher
FROM Book
WHERE price >= 10000;
이 문장에는 데이터를 어떤 순서로 읽을지, 인덱스를 사용할지 등의 물리적인 처리 방법이 직접 지정되어 있지 않다.
2.2 SQL의 사용 방식
| 대화식 SQL | SQL 클라이언트에서 질의를 직접 작성하고 실행하는 방식 |
| 삽입 SQL | 응용 프로그램에 SQL을 포함하여 데이터를 처리하는 방식 |
2.3 SQL의 분류
| DDL | 데이터베이스 객체의 구조를 정의하거나 변경·삭제 | CREATE, ALTER, DROP |
| DML | 저장된 데이터를 검색하거나 삽입·수정·삭제 | SELECT, INSERT, UPDATE, DELETE |
| DCL | 사용자에게 데이터 접근 및 사용 권한을 부여하거나 회수 | GRANT, REVOKE |
이 글에서는 강의자료의 분류에 따라 SELECT를 DML에 포함한다.
3. SELECT 문의 기본 구조
SELECT는 테이블에서 데이터를 검색하는 명령이다. 검색 결과는 행과 열로 구성된 형태로 반환된다.
SELECT 컬럼명
FROM 테이블명
WHERE 검색조건;
| SELECT | 결과에 표시할 컬럼이나 계산식 지정 |
| FROM | 검색할 테이블 지정 |
| WHERE | 검색할 행의 조건 지정 |
WHERE는 생략할 수 있으며, 생략하면 테이블의 모든 행을 검색 대상으로 한다.
3.1 원하는 컬럼 조회
실습: 모든 도서의 이름과 가격을 검색한다.
SELECT bookname, price
FROM Book;
결과에는 bookname, price 두 컬럼만 표시된다. SELECT에 작성한 컬럼의 순서가 결과의 열 순서를 결정한다.
SELECT price, bookname
FROM Book;
위 쿼리는 같은 데이터를 조회하지만 가격이 먼저, 도서이름이 나중에 표시된다.
3.2 모든 컬럼 조회
실습: 모든 도서의 도서번호, 도서이름, 출판사, 가격을 검색한다.
SELECT bookid, bookname, publisher, price
FROM Book;
테이블의 모든 컬럼을 조회할 때는 *를 사용할 수 있다.
SELECT *
FROM Book;
*는 모든 행이라는 뜻이 아니라 모든 컬럼을 선택한다는 뜻이다. 행의 선택은 WHERE 조건이 결정한다.
3.3 중복 허용과 제거: ALL, DISTINCT
일반적인 SELECT는 검색 결과의 중복을 허용한다. ALL을 명시해도 같은 의미이며, 생략할 수 있다.
SELECT publisher
FROM Book;
SELECT ALL publisher
FROM Book;
실습: 도서 테이블에 있는 출판사를 중복 없이 검색한다.
SELECT DISTINCT publisher
FROM Book;
같은 출판사의 도서가 여러 권 있더라도 결과에는 해당 출판사가 한 번만 표시된다.
DISTINCT는 선택한 컬럼 전체의 조합을 기준으로 중복을 제거한다.
SELECT DISTINCT publisher, price
FROM Book;
위 쿼리에서는 출판사가 같더라도 가격이 다르면 서로 다른 결과 행으로 남는다.
4. WHERE를 이용한 조건 검색
4.1 비교 연산자
| = | 같다 |
| <> 또는 != | 같지 않다 |
| > | 크다 |
| >= | 크거나 같다 |
| < | 작다 |
| <= | 작거나 같다 |
실습: 가격이 20,000원 미만인 도서를 검색한다.
SELECT *
FROM Book
WHERE price < 20000;
20,000원인 도서는 포함하지 않는다. 20,000원도 포함하려면 <=를 사용한다.
문자열 값은 작은따옴표로 감싸서 작성한다.
SELECT *
FROM Book
WHERE publisher = '굿스포츠';
4.2 범위 검색: BETWEEN
BETWEEN A AND B는 A 이상 B 이하의 범위를 검색하며, 양쪽 경계값을 모두 포함한다.
실습: 가격이 10,000원 이상 20,000원 이하인 도서를 검색한다.
SELECT *
FROM Book
WHERE price BETWEEN 10000 AND 20000;
비교 연산자와 AND를 사용해도 같은 조건을 나타낼 수 있다.
SELECT *
FROM Book
WHERE price >= 10000
AND price <= 20000;
4.3 집합 검색: IN, NOT IN
IN은 값이 지정한 목록에 포함되는지 검사한다.
실습: 출판사가 굿스포츠 또는 대한미디어인 도서를 검색한다.
SELECT *
FROM Book
WHERE publisher IN ('굿스포츠', '대한미디어');
NOT IN은 목록에 포함되지 않는 값을 검색한다.
실습: 출판사가 굿스포츠도 대한미디어도 아닌 도서를 검색한다.
SELECT *
FROM Book
WHERE publisher NOT IN ('굿스포츠', '대한미디어');
NULL은 일반적인 비교로 참·거짓을 확정할 수 없는 값이다. publisher가 NULL인 행은 위의 NOT IN 조건으로 선택되지 않는다. NULL 여부를 검사할 때는 IS NULL 또는 IS NOT NULL을 사용한다.
4.4 문자열 패턴 검색: LIKE
LIKE는 문자열이 특정 패턴에 맞는지 검사한다.
| % | 0개 이상의 문자 | '%축구%' |
| _ | 정확히 한 개의 문자 | '_구%' |
실습: 도서이름이 축구의 역사인 도서의 출판사를 검색한다.
SELECT publisher
FROM Book
WHERE bookname = '축구의 역사';
전체 문자열이 일치하는 조건이므로 =를 사용한다.
실습: 도서이름에 축구가 포함된 도서의 출판사를 검색한다.
SELECT publisher
FROM Book
WHERE bookname LIKE '%축구%';
%축구%는 앞뒤에 다른 문자가 있거나 없어도 문자열 안에 '축구'가 포함되면 일치한다.
-- 도서이름이 '축구'로 시작
SELECT *
FROM Book
WHERE bookname LIKE '축구%';
-- 도서이름이 '축구'로 끝남
SELECT *
FROM Book
WHERE bookname LIKE '%축구';
실습: 도서이름의 두 번째 문자가 구인 도서를 검색한다.
SELECT *
FROM Book
WHERE bookname LIKE '_구%';
첫 번째 _가 한 문자를 차지하고, 두 번째 위치의 '구'가 일치해야 한다. 이후에는 %에 의해 어떤 문자열이든 올 수 있다.
실습: 출판사가 대로 시작하고 이름이 정확히 다섯 글자인 도서를 검색한다.
SELECT *
FROM Book
WHERE publisher LIKE '대____';
'대' 한 글자와 _ 네 개를 합쳐 정확히 다섯 글자를 검사한다. 패턴 검색에는 LIKE를 사용해야 한다. publisher = '대____'는 밑줄을 와일드카드로 해석하지 않고 해당 문자열 자체와 비교한다.
4.5 복합 조건: AND, OR, NOT
| AND | 두 조건을 모두 만족 |
| OR | 두 조건 중 하나 이상 만족 |
| NOT | 조건의 논리값을 부정 |
실습: 축구에 관한 도서 중 가격이 20,000원 이상인 도서를 검색한다.
SELECT *
FROM Book
WHERE bookname LIKE '%축구%'
AND price >= 20000;
도서이름에 '축구'가 포함되면서 가격 조건도 만족해야 한다.
실습: 출판사가 굿스포츠 또는 대한미디어인 도서를 OR로 검색한다.
SELECT *
FROM Book
WHERE publisher = '굿스포츠'
OR publisher = '대한미디어';
AND와 OR를 함께 사용하면 AND가 먼저 적용된다. 조건을 묶으려면 괄호를 사용한다.
SELECT *
FROM Book
WHERE (publisher = '굿스포츠' OR publisher = '대한미디어')
AND price >= 10000;
위 조건은 두 출판사 중 하나에 속하는 도서 가운데 가격이 10,000원 이상인 도서를 검색한다.
5. ORDER BY를 이용한 정렬
ORDER BY는 조회 결과의 출력 순서를 지정한다.
SELECT 컬럼명
FROM 테이블명
WHERE 검색조건
ORDER BY 정렬컬럼 ASC 또는 DESC;
- ASC: 오름차순. 생략하면 기본값으로 적용된다.
- DESC: 내림차순.
ORDER BY가 없으면 결과 행의 순서를 보장하지 않는다. 문자열 정렬은 데이터베이스의 문자 정렬 규칙에 영향을 받는다.
5.1 하나의 컬럼으로 정렬
실습: 도서를 이름순으로 검색한다.
SELECT *
FROM Book
ORDER BY bookname ASC;
5.2 여러 컬럼으로 정렬
실습: 가격 오름차순으로 검색하고, 가격이 같으면 도서이름 오름차순으로 정렬한다.
SELECT *
FROM Book
ORDER BY price ASC, bookname ASC;
첫 번째 컬럼이 우선 정렬 기준이다. 첫 번째 값이 같을 때 두 번째 컬럼을 비교한다.
실습: 가격 내림차순으로 검색하고, 가격이 같으면 출판사 오름차순으로 정렬한다.
SELECT *
FROM Book
ORDER BY price DESC, publisher ASC;
정렬 방향은 각 컬럼에 따로 적용된다.
6. 집계 함수
집계 함수는 여러 행의 값을 모아 합계, 평균, 개수, 최솟값, 최댓값 등을 계산한다.
| SUM | 값의 합계 | SUM(saleprice) |
| AVG | 값의 평균 | AVG(saleprice) |
| COUNT | 행 또는 NULL이 아닌 값의 개수 | COUNT(*), COUNT(saleprice) |
| MIN | 최솟값 | MIN(saleprice) |
| MAX | 최댓값 | MAX(saleprice) |
SUM, AVG, MIN, MAX와 COUNT(컬럼)은 NULL을 제외하고 계산한다. COUNT(*)는 컬럼의 NULL 여부와 관계없이 행을 센다.
같은 SELECT 문의 WHERE에는 그 단계에서 계산하는 집계 함수를 직접 사용할 수 없다. WHERE는 집계 전에 개별 행을 검사하며, 집계 결과의 조건은 HAVING에서 지정한다.
6.1 SUM과 결과 컬럼의 별칭
실습: 고객이 주문한 도서의 총판매액을 구한다.
SELECT SUM(saleprice) AS 총매출
FROM Orders;
자료의 샘플 데이터 기준 결과는 다음과 같다.
| 118000 |
AS는 결과 컬럼에 별칭을 부여한다. 별칭은 결과에 표시되는 이름을 바꾸며 원본 테이블의 컬럼명을 변경하지 않는다.
6.2 특정 고객의 총판매액
실습: 고객번호가 2인 고객의 총판매액을 구한다.
SELECT SUM(saleprice) AS 총매출
FROM Orders
WHERE custid = 2;
먼저 고객번호가 2인 주문을 선택한 뒤, 선택된 주문의 판매가격을 합산한다.
| 15000 |
샘플 데이터에서 해당 고객의 판매가격은 8,000원과 7,000원이다.
6.3 여러 집계 함수 사용
실습: 전체 주문의 총판매액, 평균 판매가격, 최저 판매가격, 최고 판매가격을 구한다.
SELECT SUM(saleprice) AS 총판매액,
AVG(saleprice) AS 평균판매가격,
MIN(saleprice) AS 최저판매가격,
MAX(saleprice) AS 최고판매가격
FROM Orders;
| 118000 | 11800 | 6000 | 21000 |
평균의 소수점 표시 형식은 컬럼 자료형과 클라이언트에 따라 달라질 수 있다.
6.4 COUNT(*)와 COUNT(컬럼)의 차이
실습: 마당서점의 도서 판매건수를 구한다.
SELECT COUNT(*) AS 판매건수
FROM Orders;
샘플 데이터의 주문은 10건이므로 결과는 10이다.
COUNT(*)는 전체 행을 세고, COUNT(컬럼)은 해당 컬럼이 NULL이 아닌 행만 센다.
SELECT COUNT(*) AS 전체고객수,
COUNT(phone) AS 전화번호등록고객수
FROM Customer;
강의자료의 Customer 데이터에는 고객 5명 중 1명의 전화번호가 NULL로 표시되어 있다.
| 5 | 4 |
NULL은 숫자 0이나 빈 문자열과 다르다. 예를 들어 값이 10000, 20000, NULL인 컬럼의 평균은 NULL을 제외한 두 값으로 계산하므로 15,000이다.
6.5 집계 함수에서 DISTINCT 사용
SELECT COUNT(DISTINCT custid) AS 주문고객수
FROM Orders;
이 쿼리는 주문 건수가 아니라 주문한 서로 다른 고객의 수를 구한다. 샘플 데이터에서 주문 고객은 고객번호 1, 2, 3, 4이므로 결과는 4이다.
SUM(DISTINCT saleprice)는 같은 판매가격을 한 번씩만 합산한다. 동일한 가격의 주문도 별개의 매출이므로, 전체 판매액을 구할 때는 SUM(saleprice)를 사용한다.
7. GROUP BY를 이용한 그룹별 집계
GROUP BY는 지정한 컬럼의 값이 같은 행을 하나의 그룹으로 묶는다. 집계 함수는 각 그룹에 대해 별도로 계산된다.
SELECT 그룹컬럼, 집계함수
FROM 테이블명
GROUP BY 그룹컬럼;
GROUP BY 없이 집계하면 전체 검색 대상에 대한 집계 결과를 구한다. GROUP BY custid를 사용하면 고객별 집계 결과를 구한다.
7.1 고객별 주문 수와 총판매액
실습: 고객별 주문 도서의 총수량과 총판매액을 구한다. 결과 컬럼은 도서수량과 총액으로 표시한다.
SELECT custid,
COUNT(*) AS 도서수량,
SUM(saleprice) AS 총액
FROM Orders
GROUP BY custid
ORDER BY custid;
| 1 | 3 | 39000 |
| 2 | 2 | 15000 |
| 3 | 3 | 31000 |
| 4 | 2 | 33000 |
고객번호가 같은 주문들을 모은 뒤, 각 그룹의 행 수와 판매가격 합계를 계산한다.
이 실습 데이터는 주문 한 행을 도서 한 권의 판매로 해석하므로 COUNT(*)를 도서수량으로 표시한다. 실제 주문 테이블에 별도의 수량 컬럼이 있는 경우에는 행 수와 구매 수량이 다를 수 있다.
Orders를 대상으로 집계하므로 주문이 없는 고객번호 5는 결과에 나타나지 않는다.
7.2 SELECT 컬럼 작성 시 주의사항
그룹별 집계에서는 결과에 표시하는 일반 컬럼이 그룹 기준과 맞아야 한다.
SELECT custid, SUM(saleprice) AS 총액
FROM Orders
GROUP BY custid;
위 쿼리는 고객별 그룹을 만들고 고객번호와 총판매액을 표시한다.
반면 다음 쿼리는 한 고객의 주문에 여러 도서번호가 존재할 수 있어 문제가 된다.
-- 그룹별로 bookid 하나를 결정할 수 없는 쿼리
SELECT custid, bookid, SUM(saleprice) AS 총액
FROM Orders
GROUP BY custid;
고객번호 1의 그룹에 도서번호 1, 3, 2가 함께 존재한다면, 하나의 결과 행에 어떤 도서번호를 표시해야 하는지 정해져 있지 않다.
실습에서는 집계하지 않는 컬럼을 GROUP BY에 포함하여 작성한다. MySQL의 ONLY_FULL_GROUP_BY 설정이 활성화된 경우에는 그룹 기준으로 결정할 수 없는 일반 컬럼의 조회가 거부된다. 설정이 비활성화된 환경에서는 실행될 수 있지만, 어떤 도서번호가 선택될지 보장되지 않는다.
8. HAVING을 이용한 그룹 조건 검색
HAVING은 집계 후 만들어진 그룹을 조건에 따라 선택한다.
| 검사 대상 | 개별 행 | 그룹 |
| 적용 시점 | 그룹 생성·집계 전 | 그룹 생성·집계 후 |
| 대표 조건 | saleprice >= 8000 | COUNT(*) >= 2 |
| 역할 | 집계에 포함할 행 선택 | 결과에 포함할 그룹 선택 |
8.1 WHERE와 HAVING을 함께 사용
실습: 판매가격이 8,000원 이상인 주문을 대상으로 고객별 도서수량을 구하되, 해당 주문이 2건 이상인 고객만 출력한다.
SELECT custid,
COUNT(*) AS 도서수량
FROM Orders
WHERE saleprice >= 8000
GROUP BY custid
HAVING COUNT(*) >= 2
ORDER BY custid;
이 예제는 강의자료의 SQL에 따라 Orders.saleprice를 가격 조건으로 사용한다.
| 1 | 2 |
| 3 | 2 |
| 4 | 2 |
처리 과정은 다음과 같다.
- Orders에서 판매가격이 8,000원 이상인 주문만 선택한다.
- 선택된 주문을 고객번호별로 묶는다.
- 각 고객의 주문 수를 계산한다.
- 주문 수가 2건 이상인 고객 그룹만 남긴다.
- 고객번호 오름차순으로 출력한다.
필터링 후 고객별 주문 수는 다음과 같다.
| 1 | 2 | 통과 |
| 2 | 1 | 제외 |
| 3 | 2 | 통과 |
| 4 | 2 | 통과 |
따라서 결과의 도서수량은 고객의 전체 주문 수가 아니라, 판매가격 조건을 통과한 주문의 수이다.
8.2 HAVING은 COUNT 이외의 집계 조건에도 사용
추가 실습: 총판매액이 30,000원 이상인 고객을 검색한다.
SELECT custid,
SUM(saleprice) AS 총액
FROM Orders
GROUP BY custid
HAVING SUM(saleprice) >= 30000
ORDER BY custid;
| 1 | 39000 |
| 3 | 31000 |
| 4 | 33000 |
HAVING에는 SUM, AVG, MIN, MAX, COUNT 등을 이용한 조건을 작성할 수 있다. 집계 조건만 작성할 수 있는 것은 아니며 그룹 기준 컬럼의 조건도 사용할 수 있다. 또한 GROUP BY 없이 전체를 하나의 집계 그룹으로 처리하여 HAVING을 사용하는 경우도 있다.
9. SQL 작성 순서와 논리적 처리 순서
9.1 작성 순서
SELECT 컬럼명 또는 집계식
FROM 테이블명
WHERE 행조건
GROUP BY 그룹컬럼
HAVING 그룹조건
ORDER BY 정렬컬럼;
9.2 논리적 처리 순서
| 1 | FROM | 검색 대상 테이블 결정 |
| 2 | WHERE | 조건을 만족하는 행 선택 |
| 3 | GROUP BY | 행들을 그룹으로 묶음 |
| 4 | HAVING | 집계 결과를 이용하여 그룹 선택 |
| 5 | SELECT | 결과에 표시할 컬럼과 집계값 구성 |
| 6 | ORDER BY | 최종 결과 정렬 |
이 순서는 SQL의 의미를 이해하기 위한 논리적 처리 순서이다. DBMS의 실제 물리적 실행 순서는 실행 계획에 따라 달라질 수 있다.
WHERE가 그룹별 집계보다 앞서 적용되므로 다음과 같이 같은 단계의 집계 함수를 직접 쓰면 안 된다.
-- 잘못된 예
SELECT custid, COUNT(*) AS 도서수량
FROM Orders
WHERE COUNT(*) >= 2
GROUP BY custid;
그룹별 주문 수를 검사하려면 HAVING으로 작성한다.
SELECT custid, COUNT(*) AS 도서수량
FROM Orders
GROUP BY custid
HAVING COUNT(*) >= 2;
10. 주요 문법 정리
| 원하는 컬럼 검색 | SELECT 컬럼 FROM 테이블 |
| 모든 컬럼 검색 | SELECT * FROM 테이블 |
| 중복 제거 | SELECT DISTINCT 컬럼 |
| 행 조건 검색 | WHERE 조건 |
| 범위 검색 | BETWEEN 하한 AND 상한 |
| 목록 포함 여부 검색 | IN (값1, 값2, ...) |
| 문자열 패턴 검색 | LIKE '패턴' |
| 여러 조건 결합 | AND, OR, NOT |
| 결과 정렬 | ORDER BY 컬럼 ASC 또는 DESC |
| 결과 컬럼 별칭 지정 | 식 AS 별칭 |
| 합계·평균 계산 | SUM(컬럼), AVG(컬럼) |
| 전체 행 수 계산 | COUNT(*) |
| NULL이 아닌 값의 수 계산 | COUNT(컬럼) |
| 최솟값·최댓값 계산 | MIN(컬럼), MAX(컬럼) |
| 그룹별 집계 | GROUP BY 컬럼 |
| 그룹 조건 검색 | HAVING 조건 |
실습문제
1-(1) 도서번호가 1인 도서의 이름
SELECT bookname
FROM Book
WHERE bookid = 1;
1-(2) 가격이 20,000원 이상인 도서의 이름
SELECT bookname
FROM Book
WHERE price >= 20000;
1-(3) 박지성의 총구매액
SELECT SUM(saleprice) AS 총구매액
FROM Orders
WHERE custid = 1;
1-(4) 박지성이 구매한 도서의 수
SELECT COUNT(*) AS 구매도서수
FROM Orders
WHERE custid = 1;
2-(1) 마당서점 도서의 총개수
SELECT COUNT(*) AS 도서총개수
FROM Book;
2-(2) 마당서점에 도서를 출고하는 출판사의 총개수
SELECT COUNT(DISTINCT publisher) AS 출판사총개수
FROM Book;
2-(3) 모든 고객의 이름과 주소
SELECT name, address
FROM Customer;
2-(4) 2024년 7월 4일~7월 7일 사이에 주문받은 도서의 주문번호
SELECT orderid
FROM Orders
WHERE orderdate >= '2024-07-04'
AND orderdate < '2024-07-08';
2-(5) 2024년 7월 4일~7월 7일 사이에 주문받은 도서를 제외한 도서의 주문번호
SELECT orderid
FROM Orders
WHERE orderdate < '2024-07-04'
OR orderdate >= '2024-07-08';
2-(6) 성이 ‘김’ 씨인 고객의 이름과 주소
SELECT name, address
FROM Customer
WHERE name LIKE '김%';
2-(7) 성이 ‘김’ 씨이고 이름이 ‘아’로 끝나는 고객의 이름과 주소
SELECT name, address
FROM Customer
WHERE name LIKE '김%아';
소감
잊고 있었던 개념을 되짚어보는 계기가 되어 좋았다.
'데이터베이스시스템특론' 카테고리의 다른 글
| 2.관계데이터모델 (1) | 2026.09.29 |
|---|---|
| 1.데이터베이스시스템 (1) | 2026.09.15 |











