[MySQL]SELECT문

2024. 8. 4. 23:49MySQL/SQL 기본

SELECT문은 원하는 데이터를 가져와 주는 명령이다.

아래는 구문 형식이다. 버전에 따라 내용이 조금씩 다르지만 큰 틀은 다르지 않다. 중요한 부분에는 ####을 추가하였다. 

SELECT [ ALL | DISTINCT | DISTINCTROW ]
       [ HIGH_PRIORITY ]
       [ STRAIGHT_JOIN ]
       [ SQL_SMALL_RESULT | SQL_BIG_RESULT ] [ SQL_BUFFER_RESULT ]
       [ SQL_CACHE | SQL_NO_CACHE ]
       [ SQL_CALC_FOUND_ROWS ]
expressions
FROM tables           #####
[WHERE conditions]    #####
[GROUP BY expressions] #######
[HAVING condition] ######
[ORDER BY expression [ ASC | DESC ]]  #######
[LIMIT [offset_value] number_rows | LIMIT number_rows OFFSET offset_value]
[PROCEDURE procedure_name]
[INTO [ OUTFILE 'file_name' options 
       | DUMPFILE 'file_name'
       | @variable1, @variable2, ... @variable_n]
[FOR UPDATE | LOCK IN SHARE MODE];

 

가장 자주 쓰이는 형식은 다음과 같다. 

SELECT 열 이름
FROM 테이블이름
WHERE 조건

 

https://www.techonthenet.com/mysql/select.php

 

MySQL: SELECT Statement

MySQL: SELECT Statement This MySQL tutorial explains how to use the MySQL SELECT statement with syntax and examples. Description The MySQL SELECT statement is used to retrieve records from one or more tables in MySQL. Syntax In its simplest form, the synta

www.techonthenet.com

 

SELECT와 FROM 

SELECT * FROM titles;

 

*은 모든 열을 의미한다. FROM 다음은 테이블/뷰 등의 항목이다. 'titles 테이블에서 모든 열의 내용을 가져오라'는 의미이다. 

 

본래 테이블의 전체 이름은 '데이터베이스이름.테이블이름' 형식으로 표현한다. 하지만 이름을 생략하면 선택된 데이터베이스 이름이 자동으로 붙게 할 수 있다. 

 

여러열을 가져오고 싶으면 콤마(,)로 구분하면 된다. 

SELECT first_name, last_name, gender FROM employees;

 

열 이름의 별칭

열 이름을 별도의 별칭(Alias)로 지정할 수 있다. 열 이름 뒤에 AS 별칭 형식으로 붙이면 된다. 하지만, 중간에 공백이 있다면 꼭 작은 따옴표로 감싸주어야 한다. AS는 생략이 가능하다. 

SELECT first_name AS 이름, gender 성별, hire_date '회사 입사일'
FROM employees;

 

특정한 조건의 데이터만 조회하는 SELECT ... FROM ... WHERE

WHERE절은 특정한 조건을 줘서 원하는 데이터만 보고 싶을 때 사용한다. 

SELECT 필드이름 FROM 테이블이름 WHERE 조건식;

 

만약 usertbl에서 이름이 '김경호'라는 사람을 찾는다면 다음과 같이 쓴다. 

SELECT * FROM usertbl WHERE name = '김경호';

 

WHERE절에는 관계대명사도 사용이 가능하다. 

SELECT userID, Name FROM usertbl WHERE birthYear >= 1970 OR height >= 182;

 

~했거나 ~또는 등은 OR연산자로, ~하고, ~면서, ~그리고는 AND 연산자를 이용하면 된다. 그 외에도 =, <, >, <=, >=, != 등과 NOT, AND, OR 등을 조합해서 사용 가능하다. 

 

BETWEEN ... AND과 IN() 

SELECT name, height 
FROM usertbl
WHERE height >= 180 AND height <= 183;

 

위처럼 연속적인 값을 가지는 경우에는 BETWEEN ...  AND를 이용하여 이렇게 바꿀 수 있다. 

SELECT name, height 
FROM usertbl
WHERE height BETWEEN 180 AND 183;

 

연속적이 아니라면 IN()을 이용할 수 있다. 하나라도 해당하면 출력한다. 

SELECT name, addr
FROM usertbl
WHERE addr IN('경남', '전남', '경북');

 

LIKE

LIKE는 문자열을 검색하는 연산자이다.

%는 무엇이든 허용한다는 의미이다. 즉, '김'이 제일 앞 글자인 것을 추출한다. 

SELECT name, height
FROM usertbl 
WHERE name LIKE '김%';

 

한 글자와 매치하기 위해서는 '_'를 사용한다. 조건에 '_용%'을 사용하면 앞에 아무거나 한 글자가 오고 두 번째는 용, 세번째 이후는 몇 글자든 아무거나 오는 값을 추출해준다. 

SELECT name, height
FROM usertbl
WHERE name LIKE '_종신';

 

ANY/ALL

서브쿼리란 쿼리 안에 쿼리가 있는 것을 의미한다.

 

예를 들어서, 김경호의 키를 모르는 채 김경호보다 키가 큰 사람을 찾는 경우에는 다음과 같이 검색하면 된다. 

SELECT name, height
FROM usertbl
WHERE height > (SELECT height FROM usertbl WHERE Name = '김경호');

 

후반부의 서브 쿼리는 '김경호'의 키인 177을 반환하여 결국 177 초과한 키를 찾는 것과 다름없는 코드다. 

 

그런데 '경남'에 사는 사람보다 키가 큰 사람을 찾는다면 어떻게 해야할까? '경남'에 사는 사람이 한 사람이 아닐 것이다. 예를 들어 김범수(173), 윤종신(170)이 있다고 치자. 그러면 오류가 발생한다. 이 때 ANY/ALL을 사용할 수 있다. 

SELECT name, height FROM usertbl
WHERE height = ANY(SELECT height FROM usertbl WHERE addr = '경남');

 

ANY는 여러 조건 중에 하나라도 만족하면 출력한다. 즉, 예시에서는 170이상을 검색한다. IN과 동일한 의미이다. 

ALL은 여러 조건을 모두 만족하는 사람을 출력한다. 즉, 예시에서는 173이상을 검색한다. 

 

원하는 순서대로 정렬하여 출력: ORDER BY

 

결과물에 영향을 미치지 않지만 출력 순서를 조절하는 구문이다. 오름차순이 기본값이라 생략이 가능하고 ASC로 입력한다. 내림차순은 DESC이다. 

SELECT name, mDate FROM usertbl ORDER BY mDate DESC;

 

중복된 것은 하나만 남기는 DISTNCT

회원 테이블에서 회원의 거주지를 출력해보자. 

select addr from usertbl;

 

중복을 제거하기 위해 DISTINCT를 사용해보자. 

SELECT DISTINCT addr FROM usertbl;

 

DISTINCT 위치를 주의하자. 중복된 것이 1개씩만 보여주면서 출력된다는 것을 보여준다. 

 

출력하는 개수를 제한하는 LIMIT

입사일이 오래된 직원 5명의 사원번호를 알고 싶으면 LIMIT을 통해 출력 개수를 사용할 수 있다. 

USE employees;
SELECT emp_no, hire_date FROM employees
ORDER BY hire_date ASC
LIMIT 5;

LIMIT절은 'LIMIT 시작, 개수' 또는 'LIMIT 개수 OFFSET 시작' 형식으로 사용할 수 있다. 시작은 0부터 시작한다. 5개를 출력하기 위해서는 다음과 같이 사용할 수 있다. 

USE employees;
SELECT emp_no, hire_date FROM employees
ORDER BY hire_date ASC
LIMIT 0, 5; -- LIMIT 5 OFFSET 0과 동일

 

테이블을 복사하는 CREATE TABLE ... SELECT 

buytbl을 buytbl2로 복사하는 구문은 다음과 같다. 

USE sqldb;
CREATE TABLE buytb12 (SELECT * FROM buytbl);
SELECT * FROM buytb12;

 

일부 열만 복사할 수도 있다. 

CREATE TABLE buytbl3 (SELECT userID, prodName FROM buytbl);
SELECT * FROM buytbl3;

 

다만, Primary Key 및 Foreign Key 등의 제약 조건은 복사되지 않는다. 

 

GROUP BY 및 HAVING 그리고 집계 함수 

GROUP BY절은 그룹으로 묶어주는 역할을 한다. 보통 집계 함수와 함께 사용된다. 예를 들어서 사용자가 구매한 물품의 개수를 보기 위해서는 다음과 같이 할 수 있다. 

SELECT userID, SUM(amount) 
FROM buytbl
GROUP BY userID;

각 사용자(userID)별로 구매한 개수(amount)를 합쳐서 출력하였다. 그런데 결과 열에 제목이 함수 그대로 나오기 떄문에 AS를 이용해서 변경하는 것이 좋다. 

SELECT userID AS '사용자 아이디', SUM(amount) AS '총 구매 개수'
FROM buytbl
GROUP BY userID;

구매액은 가격(price) * 수량(amount)이므로 다음과 같이 출력할 수 있다. 

SELECT userID AS '사용자 아이디', SUM(amount * price) AS '총 구매액'
FROM buytbl
GROUP BY userID;

 

Having절

구매액이 1000이상인 사용자를 찾기 위해 쿼리를 짰는데 문제가 발생했다. 

SELECT userID AS '사용자', SUM(price*amount) AS '총구매액'
FROM buytbl
WHERE SUM(price*amount) > 1000
GROUP BY userID; //오류 발생

 

WHERE절은 집계 함수에 사용할 수 없다. 대신에 HAVING을 사용해야 한다. 집계 함수에 대해 조건을 제한하는 것이라고 생각하면 된다. 다만, GROUP BY 다음에 온다는 점에 차이가 있으니 기억해야 한다. 

SELECT userID AS '사용자', SUM(price*amount) AS '총구매액'
FROM buytbl
GROUP BY userID
HAVING SUM(price*amount) > 1000;

ROLLUP

총합 또는 중간 합계가 필요하면 GROUP BY와 함께 WITH ROLLUP문을 사용한다. GROUP BY 뒤에 나오는 컬럼별로 합계를 구해준다. 합계값만 추가해서 나머지 필드 이름은 NULL값이 들어간다. 

SELECT num, groupName, SUM(price * amount) AS '비용'
FROM buytbl
GROUP BY groupName, num WITH ROLLUP;

 

'MySQL > SQL 기본' 카테고리의 다른 글

[MySQL] 데이터 형식 변환 함수  (0) 2024.08.13
[MySQL] 변수  (0) 2024.08.12
[MySQL] DELETE FROM  (0) 2024.08.09
[MySQL]UPDATE문  (0) 2024.08.08
[MySQL] 집계 함수  (0) 2024.08.05