기억의 실마리
2023. 1. 30. 21:34

MySQL의 SELECT기능 다뤄보기

이 게시글은 전반적으로  SELECT기능을 기술한 것이 대부분이다.

이 게시글에 모든 예시는 아래 링크를 통해서 사용해 볼 수 있다.스키마 이름이나 칼럼이름 역시 같아 결과값이 그대로 적용되어 보여진다.

https://www.w3schools.com/mysql/trymysql.asp?filename=trysql_select_all

 

MySQL Tryit Editor v1.0

WebSQL stores a Database locally, on the user's computer. Each user gets their own Database object. WebSQL is supported in Chrome, Safari, and Opera. If you use another browser you will still be able to use our Try SQL Editor, but a different version, usin

www.w3schools.com

 

데이터 Customers에서 모든내용 보기

SELECT * FROM Customers;
-- 이와 같이 주석을 달 수 있다.

 

원하는 column(열)만 골라서 보기

SELECT CustomerName FROM Customers;
--Customers스키마에서 CustomerName의 열만 골라서 보여준다.

SELECT CustomerName, ContactName, Country
FROM Customers;
--이렇게 다중으로 볼 수도 있다.

 

테이블의 column이 아닌 값 보기

SELECT
  CustomerName, 1, 'Hello', NULL
FROM Customers;
-- 1과 Hello와 NULL은 테이블의 column이 아니다.
-- 하지만 위와같이 입력하면 해당 내용과 같은 것들만 보여진다.

 

원하는 row(행)만 선택해서 보기

SELECT * FROM Orders
WHERE EmployeeID = 3;
-- 데이터 Orders에서 모든것 중에서 WHERE(조건문)을
-- 사용해서 EmployeeID가 3인 행만 보여지게 된다.

SELECT * FROM OrderDetails 
WHERE Quantity < 5;
-- 이런식으로 조건문을 꼭 등호가 아니여도 된다.
-- if문처럼 TRUE or FALSE로 반환되도록 잘 붙여주면 된다.

 

원하는 데이터 순서대로 가져오기

ORDER BY 구문을 사용하여 특정 column을 기준으로 잡고
-- 오름, 내림차순으로 볼 수 있다. Default는 오름차순이다.
-- ASC = 오름차순  /  DESC = 내림차순

SELECT * FROM Customers
ORDER BY ContactName;
-- 아무것도 지정해주지 않았기 때문에 ContactName을 기준으로
-- 오름차순으로 정렬된다.

SELECT * FROM OrderDetails
ORDER BY ProductID ASC, Quantity DESC;
-- 이런 경우 먼저 나온 column이 먼저 기준이 되어 정렬되고
-- 먼저 정렬된 것을 기준으로 그 다음 column이 정렬된다.

 

원하는 만큼만 데이터 가져오기

-- LIMIT {가져올 갯수} 또는 LIMIT {건너뛸 갯수}, {가져올 갯수} 를 사용하여,
-- 원하는 위치에서 원하는 만큼만 데이터를 가져올 수 있다.

SELECT * FROM Customers
LIMIT 10;
-- (첫줄부터 10까지)

SELECT * FROM Customers
LIMIT 0, 10;
-- (0~10까지)

SELECT * FROM Customers
LIMIT 30, 10;
-- (30번째줄부터 시작해서 10줄까지)

 

원하는 별명(alias)으로 데이터 가져오기

SELECT
  CustomerId AS ID,
  CustomerName AS NAME,
  Address AS ADDR
FROM Customers;

SELECT
  CustomerId AS '아이디',
  CustomerName AS '고객명',
  Address AS '주소'
FROM Customers;

 

 

사칙연산

 

1. 기본 사칙연산

 

  • +, -, *, /
    각각 더하기, 빼기, 곱하기, 나누기
  • %, MOD
    나머지
SELECT 1 + 2;
SELECT 5 - 2.5 AS DIFFERENCE;
SELECT 3 * (2 + 4) / 2, 'Hello';
SELECT 10 % 3;

 

  • 문자열에 사칙연산을 가하면 0으로 인식한다.
SELECT 'ABC' + 3;
SELECT 'ABC' * 3;
SELECT '1' + '002' * 3;
-- 숫자로 구성된 문자열은 숫자로 자동인식

 

  • 또 다른 예제
SELECT
  OrderID + ProductID
FROM OrderDetails;
-- OrderID의 숫자와 ProductID의숫자가 더해진다.

SELECT
  ProductName,
  Price / 2 AS HalfPrice
FROM Products;
-- ProductName과 Price를 나누기 2한 결과값의
-- 데이터이름을 HalfPrice로 보여지게 했다.

 

 

2. 참/거짓 관련 연산자

 

  • MySQL에서는 TRUE는 1, FALSE는 0으로 저장됩니다.
SELECT TRUE, FALSE;
-- true = 1  , false = 0

 

  • 또 다른 예제
SELECT !TRUE, NOT 1, !FALSE, NOT FALSE;
-- !true = 0, not 1 = 0, !false = 1, not false = 1
-- 트루의 반대는 펄스라서 0, not은 아니다의 뜻

SELECT 0 = TRUE, 1 = TRUE, 0 = FALSE, 1 = FALSE;
-- 0, 1, 1, 0
-- 1=true이고 0=false이기 때문이다.

SELECT * FROM Customers WHERE City = 'Berlin';
-- 전체 데이터에서 where조건문에 의해서 시티가 베를린인 것을  select한다.

 

  • IS = 양쪽이 모두 TRUE 또는 FALSE
    IS NOT = 한쪽은 TRUE, 한쪽은 FALSE
SELECT TRUE IS TRUE;
-- true는 true가 맞다.  return 1;

SELECT TRUE IS NOT FALSE;
-- true는 false가 아니다. return 1;

SELECT (TRUE IS FALSE) IS NOT TRUE;
-- true는 false이다. <= 이것은 true가 아니다. return 1;

 

  • AND, && = 양쪽이 모두 TRUE일 때만 TRUE
    OR, || = 한쪽은 TRUE면 TRUE
    Javascript와 동일하게 작동한다.
SELECT TRUE AND FALSE, TRUE OR FALSE;
-- Javascript ver.
-- true && false = false, true || false = true

SELECT 2 + 3 = 6 OR 2 * 3 = 6;
-- 5와 6이지만 or을 사용했기때문에 true를 반환.

SELECT * FROM Orders
WHERE
  CustomerId = 15 AND EmployeeId = 4;
-- and를 썼기 때문에 두 조건 모두 충족하는 데이터만 보임.
-- CustomerId = 15 OR EmployeeId = 4; 이면 두 조건중 하나만
-- 충족해도 보여지게 된다.

SELECT * FROM Products 
WHERE
  ProductName = 'Tofu' OR CategoryId = 8;
-- 두 조건중 하나라도 충족한 경우 모두 보여진다.

SELECT * FROM OrderDetails
WHERE
  ProductId = 20
  AND (OrderId = 10514 OR Quantity = 50);
-- ProductId = 20이면서 OrderId = 10514이거나
-- Quantity = 50인 데이터를 모두 보여준다.

 

  • = 양쪽 값이 같음
    !=, <> 양쪽 값이 다름
    >, < (왼쪽, 오른쪽) 값이 더 큼
    >=, <= (왼쪽, 오른쪽) 값이 같거나 더 큼
SELECT 1 = 1, !(1 <> 1), NOT (1 < 2), 1 > 0 IS NOT FALSE;
-- 1, 1, 0, 1

SELECT 'A' = 'A', 'A' != 'B', 'A' < 'B', 'A' > 'B';
-- 1, 1, 1, 0
-- 알파뱃은 나중에 나오는 알파뱃일수록 크다고 판정된다.

-- MySQL의 기본 사칙연산자는 대소문자 구분을 하지 않는다.
SELECT 'A' = 'a';
-- true이다. 구분하지 않기때문에

SELECT
  ProductName, Price,
  Price > 20 AS EXPENSIVE 
FROM Products;
-- ProductName과 Price데이터를 보여주고
-- Price가 20보다 높으면 EXPENSIVE라는 별명에
-- 1이 추가된다 (20보다 높으면 참이 되기 때문)

SELECT
  ProductName, Price,
  NOT Price > 20 AS CHEAP 
FROM Products;
-- ProductName과 Price데이터를 보여주고
-- Price가 20보다 크지 않은 것(not)은 CHEAP이라는 별명에
-- 1이 추가 된다.

 

  • BETWEEN {MIN} AND {MAX} = 두 값 사이에 있다.
    NOT BETWEEN {MIN} AND {MAX} =  두 값 사이가 아닌 곳에 있다.
SELECT 5 BETWEEN 1 AND 10;
-- 5는 1과 10 사이에 있다. = true

SELECT 'banana' NOT BETWEEN 'Apple' AND 'camera';
-- a와 c사이에 b가 있는건 맞지만 not이 붙어서 false를 반환한다.

SELECT * FROM OrderDetails
WHERE ProductID BETWEEN 1 AND 4;
-- OrderDetails에서 ProductID가 1~4인 데이터만 보여진다.

SELECT * FROM Customers
WHERE CustomerName BETWEEN 'b' AND 'c';
-- b와 c사이는 b로 시작하는 모든 문장을 말한다.
-- c를 넘기진 말아야 하니 c로시작하는 문장은 제외된다.

 

  • IN (...) 괄호 안의 값들 가운데 있다.
    NOT IN (...) 괄호 안의 값들 가운데 없다.
SELECT 1 + 2 IN (2, 3, 4) 
-- 1+2 = 3 괄호안에 3 있으니까 true를 반환한다.

SELECT 'Hello' IN (1, TRUE, 'hello') 
-- hello가 있으니 true를 반환. 대소문자를 구분안한다는 것을 기억하자.

SELECT * FROM Customers
WHERE City IN ('Torino', 'Paris', 'Portland', 'Madrid') 
-- Customers데이터에서 City내부에 
-- 'Torino', 'Paris', 'Portland', 'Madrid'가 있는 데이터만 보여진다.

 

  • LIKE '... % ...' 0~N개 문자를 가진 패턴
    LIKE '... _ ...' _ 갯수만큼의 문자를 가진 패턴
SELECT
  'HELLO' LIKE 'hel%',   = 1
-- hel이후 어떤 문자가 와도 true

  'HELLO' LIKE 'H%',   = 1
-- h로 시작하고 그 이후 어떤 문자가 있던 true

  'HELLO' LIKE 'H%O',   = 1
-- H로 시작해서 O로 끝나기만 하면 true

  'HELLO' LIKE '%O',   = 1
-- 앞에 몇글자가 있든 무슨 글자가 있든 O로 끝나면 true

  'HELLO' LIKE '%HELLO%',  = 1
-- HELLO라는 글자 앞과 뒤에 어떤 문자가 얼마나 있든
-- HELLO만 있다면 true, 0~N개라서 아무것도 없이 HELLO여도 true

  'HELLO' LIKE '%H',   = 0 
-- H로 끝나야 true인데 HELLO이기때문에 O로 끝나서 false를 반환한다.

  'HELLO' LIKE 'L%'   = 0
-- L로 시작해야 하는데 HELLO라서 false를 반환한다.

 

연산자  총정리!

SELECT
  'HELLO' LIKE 'HEL__',    = 1
  'HELLO' LIKE 'h___O',    = 1
  'HELLO' LIKE 'HE_LO',    = 1
  'HELLO' LIKE '_____',    = 1
  'HELLO' LIKE '_HELLO',    = 0
  'HELLO' LIKE 'HEL_',    = 0
  'HELLO' LIKE 'H_O'    = 0
-- 무슨 글자든 _ 의 갯수에 맞춰서 트루와 펄스를 반환한다.


/*

[ +, -, *, / ] === 각각 더하기, 빼기, 곱하기, 나누기

[ %, MOD ] === 나머지

[ IS ] === 양쪽이 모두 TRUE 또는 FALSE

[ IS NOT] === 한쪽은 TRUE, 한쪽은 FALSE

[ AND, && ] === 양쪽이 모두 TRUE일 때만 TRUE

[ OR, || ]=== 한쪽은 TRUE면 TRUE

[ = ] === 양쪽 값이 같음

[ !=, <> ] === 양쪽 값이 다름

[ >, < ] ===(왼쪽, 오른쪽) 값이 더 큼

[ >=, <= ] === (왼쪽, 오른쪽) 값이 같거나 더 큼

[ BETWEEN {MIN} AND {MAX} ] === 두 값 사이에 있음

[ NOT BETWEEN {MIN} AND {MAX} ] === 두 값 사이가 아닌 곳에 있음

[ IN (...)] === 괄호 안의 값들 가운데 있음

[ NOT IN (...) ] === 괄호 안의 값들 가운데 없음

[ LIKE '... % ...' ] === 0~N개 문자를 가진 패턴

[ LIKE '... _ ...' ] === _ 갯수만큼의 문자를 가진 패턴

*/

 

 

 

 ※  예시가 너무 방대하여 이해가 난해한 경우만 간략한 예시를 작성했다.  ※

Math

  • ROUND = 반올림
    CEIL = 올림
    FLOOR = 내림

  • ABS = 절대값
  • GREATEST() = 가장 큰 값
  • LEAST() = 가장 작은 값

  • MAX()  = 가장 큰 값
    MIN()  = 가장 작은 값
    COUNT()  = 갯수 (NULL값 제외)
    SUM()  = 총합
    AVG()  = 평균 값

  • TRUNCATE(N, n) = N을 소숫점 n자리까지 선택

 

문자열 케이스

  • UCASE, UPPER = 모두 대문자로
    LCASE, LOWER = 모두 소문자로
  • CONCAT(...) = 괄호 안의 인자(내용)를 이어붙임
    SELECT CONCAT('HELLO', ' ', 'THIS IS ', 2021)
    = (HELLO THIS IS 2021) 숫자도 문자열로 자동변환되어 더해진다.

    CONCAT_WS(S, ...) = 첫번째 인자로 이어붙임
    SELECT CONCAT_WS('-', 2021, 8, 15, 'AM')
    = (2021-8-15-AM)

  • SUBSTR(), SUBSTRING() = 주어진 값에 따라 문자열 자름
    SELECT
    SUBSTR('ABCDEFG', 3),
    = 왼쪽에서 3번째 문자부터 읽어온다. (CDEFG)

    LEFT() = 왼쪽부터 N글자
    RIGHT() = 오른쪽부터 N글자

 

그룹함수

 

1. 예시

SELECT Country FROM Customers
GROUP BY Country;
-- 중복되는 것들을 모두 하나로 묶어서 하나씩만 보여진다.


SELECT 
  Country, City,
  CONCAT_WS(', ', City, Country) as 'city, country'
FROM Customers
GROUP BY Country, City;
-- GROUP BY를 컨트리와 시티에 해주어서 Country의 값이 같은
-- 값이라도 City의 값이 다르면 다 보여준다.

 

2. 그룹함수 활용하기

SELECT
  COUNT(*), OrderDate
FROM Orders
GROUP BY OrderDate;
-- 그룹으로 묶인 값들의 갯수도 같이 볼 수 있다.

SELECT
  ProductID,
  SUM(Quantity) AS QuantitySum
FROM OrderDetails
GROUP BY ProductID
ORDER BY QuantitySum DESC;

SELECT
  CategoryID,
  MAX(Price) AS MaxPrice, 
  MIN(Price) AS MinPrice,
  TRUNCATE((MAX(Price) + MIN(Price)) / 2, 2) AS MedianPrice,
  TRUNCATE(AVG(Price), 2) AS AveragePrice
FROM Products
GROUP BY CategoryID;

SELECT 
  CONCAT_WS(', ', City, Country) AS Location,
  COUNT(CustomerID)
FROM Customers
GROUP BY Country, City;

Tryit Editor을 통해서 사용해보면 결과값을 확인할 수 있다.

 

  • WITH ROLLUP = 전체의 집계값 (ORDER BY와는 사용불가능)
SELECT
  Country, COUNT(*)
FROM Suppliers
GROUP BY Country
WITH ROLLUP;
-- COUNT의 합계가 가장 밑에 추가된다.

 

  • HAVING = 그룹화된 데이터 걸러내기
SELECT
  Country, COUNT(*) AS Count
FROM Suppliers
GROUP BY Country
HAVING Count >= 3;
-- Count로 집계된 데이터중 3과 같거나 큰 값만 보여준다.

 

  • WHERE는 그룹하기 전 데이터, HAVING은 그룹 후 집계에 사용한다.
SELECT
  COUNT(*) AS Count, OrderDate
FROM Orders
WHERE OrderDate > DATE('1996-12-31')
GROUP BY OrderDate
HAVING Count > 2;
-- WHERE로 1996-12-31보다 높은 수의 날짜들로 거른 후
-- OrderDate를 그룹화 시켜준 후 그룹화가 되었으니 HAVING으로 2보다 높은 수만 보여준다.

SELECT
  CategoryID,
  MAX(Price) AS MaxPrice, 
  MIN(Price) AS MinPrice,
  TRUNCATE((MAX(Price) + MIN(Price)) / 2, 2) AS MedianPrice,
  TRUNCATE(AVG(Price), 2) AS AveragePrice
FROM Products
WHERE CategoryID > 2
GROUP BY CategoryID
HAVING
  AveragePrice BETWEEN 20 AND 30
  AND MedianPrice < 40;
-- 이와같은 예시로 WHERE로 먼저 데이터를 걸러준 후 GROUP BY를
-- 사용해서 묶어준 후 HAVING으로 걸러낼 수 있다.

 

  • DISTINCT = 중복된 값들을 제거한다.
    GROUP BY 와 달리 집계함수가 사용되지 않는다.
    GROUP BY 와 달리 정렬하지 않으므로 더 빠르다.
SELECT DISTINCT CategoryID
FROM Products;
-- 위의 GROUP BY를 사용한 쿼리와 결과 비교
-- GROUP BY는 오름차순(Default)으로 정렬되어 보여주지만 DISTINCT는
-- 정렬하지 않은채로 데이터를 보여준다.

SELECT COUNT DISTINCT CategoryID
FROM Products;
-- 오류 발생
-- DISTINCT는 집계함수를 사용할 수 없어서 오류가 발생한다.

 

  • GROUP BY와 DISTINCT 함께 활용
SELECT
  Country,
  COUNT(DISTINCT CITY)
FROM Customers
GROUP BY Country;
-- 그룹으로 묶어줄때 집계함수 내부에 포함시켜 줄 수 있다.

 

 

마치며...

포스팅을 하다보니 너무 방대해서 포스팅을 나눠서 해야할 필요성을 느껴, 이만작성하고 다음 포스팅에서 상관 서브쿼리와 비상관 서브쿼리, JOIN 등에 대해서 포스팅을 마저 해야겠다.

 

예시자료 출처 -  https://www.yalco.kr/lectures/sql/

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

[ MySQL ] 상관,비상관 서브쿼리와 JOIN  (0) 2023.02.02
[ MySQL ] 데이터베이스  (4) 2023.01.29