SQL 문법이 정리되지 않은 상태에서 ORM을 사용하여 DB를 다루다가
SQL 문법이 거의 그대로 쓰이는 typeORM의 query builder를 만나고
row query에 대해 정리하는 시간을 가져야겠다는 생각이 들었습니다.
또한 종종 문제 해결을 위해 raw query를 알고 있어야 할 때가 생기기도 하고
ORM이 방언이라 한다면 SQL은 표준어와 같은 느낌이라 예제에서 자주 접하게 되어
시간이 지날 수록 필수로 알고있어야 한다는 생각이 강렬하게 듭니다.
ORM들이 SQL 문법에 기초하여 만들어지기도 하고요.
"SQL 첫걸음"이라는 책을 1회독 한 후 정리한다는 느낌으로 작성하기 때문에
SQL에 대해 완전히 생소하신 분께는 친절하지 않은 글일 수 있습니다.
🥕 예제 링크
🌈 SELECT * FROM Custormers;
SELECT 뒤에 나오는 *(asterisk)는 테이블의 모든 열(column)을 선택한다는 의미입니다.
FROM 뒤에는 선택하려는 테이블 이름입니다.
결과: 특정 테이블의 모든 column이 선택됩니다.
🌈 SELECT CustomerName From Customers;
특정 column을 지정하려면 SELECT 뒤에 해당 colume 이름을 명시합니다.
결과: Customers 테이블에서 CustomerName 컬럼만 선택됩니다.
🌈 SELECT CustomerName, City, Country From Customers;
SELECT 뒤에 여러개의 colume을 지정할 수도 있습니다.
column끼리의 구분은 comma(,)로 해줘야 합니다.
결과: Customers 테이블에서 CustomerName, City, Country colume이 선택됩니다.
🌈 SELECT CustomerName, 1, null, 'hi' FROM Customers;
Colume이 아닌 것들을 출력할 수도 있습니다.
CustomerName 뒤 1, null, 'hi'은 자료형들을 표시한 것입니다.
결과: 각각 colume이 되어 출력됩니다.
🌈 SELECT * FROM Customers WHERE CustomerID = 1;
Customers 테이블에서 CustomerID가 1인 데이터만 선택하려 합니다.
WHERE 뒤에 조건을 지정할 수 있습니다.
결과: CustomerID가 1인 행만 선택됩니다.
🌈 SELECT CustomerName, Country FROM Customers WHERE CustomerID = 1;
SELECT 뒤에 원하는 Culomn만 선택해서 가져올 수 있습니다.
결과: CustomerID가 1인 행에서 CustomerName, Country만 선택됩니다.
🌈 SELECT * FROM Customers WHERE CustomerId < 11;
🌈 SELECT * FROM OrderDetails ORDER BY ProductID DESC;
ASC: 오름차순(ascending), 따로 지정하지 않으면 기본값으로 지정됩니다.
DESC : 내림차순(descending)
결과: OrderDetails 테이블의 ProductID를 기준으로 내림차순으로 정리됩니다.
🌈 SELECT * FROM OrderDetails ORDER BY ProductID, Quantity DESC;
ORDER BY 뒤에 정렬하고 싶은 Column을 여러개 두어 먼저 정렬된 기준 안에서
또 다시 정렬을 할 수 있습니다.
순서는 먼저 작성된 column이 먼저 정렬된 후 먼저 정렬된 기준 안에서
다음에 작성된 기준에 따라 새롭게 정렬이 됩니다.
결과: OrderDetails 테이블의 ProductID가 먼저 오름차순으로 정리된 후에
ProductID의 정렬기준 안에서 Quantity 기준으로 내림차순으로 정리됩니다.
🌈 SELECT * FROM OrderDetails LIMIT 10;
필요하지 않는 데이터까지 부르면 서버에 무리가 가고 성능이 저하되기 때문에 이를 방지하기 위하여 LIMIT을 사용합니다.
LIMIT 뒤에 원하는 데이터 row 갯수만큼의 숫자를 적어주면 됩니다.
결과: OrderDetails 테이블의 row 10개를 선택합니다.(1 ~ 10)
🌈 SELECT * FROM OrderDetails LIMIT 5, 10;
LIMIT 뒤에 2개의 숫자를 넣으면 앞의 숫자만큼의 row를 건너뛴 후 10개의 row를 선택합니다.
게시판의 글 목록과 같이 페이지마다 보여줄 데이터를 구분할 때 사용합니다.
1페이지에서 10개의 글을 보여줬다면 2페이지에서는 앞의 10개의 글은 건너 뛰고 보여줘야하는데 이럴 때 사용합니다(pagenation)
결과: OrderDetails 테이블에서 5개의 row를 건너 뛴 다음 10개의 row를 선택합니다.(6 ~ 15)
🌈 SELECT CustomerName AS Name, ContactName AS NikcName FROM Customers;
선택한 Column 이름에 별명(alias)을 붙여 불러올 수 있습니다.
SELECT의 column 이름 뒤에 AS를 붙이고 이어서 원하는 별명을 적으면 됩니다.
결과: CustomerName은 Name으로, ContactName은 NikcName으로 column 이름이 변경되어 선택됩니다.(영구적으로 column 이름이 변경되는 것은 아닙니다)
SELECT CustomerName AS '고객명', City AS '도시', Country AS '국가'
FROM Customers
WHERE City = 'London' OR Country = 'UK'
ORDER BY CustomerName
LIMIT 0, 5
🌈 SELECT 1 + 2;
🌈 SELECT 5 - 2.5 AS '사칙';
🌈 SELECT 2 * (10 / 2) % 2 AS '계산결과', '열정맨';
🌈 SELECT '하' + 2 + '!';
🌈 SELECT '1' + 2;
🌈 SELECT CustomerID, EmployeeID, CustomerID + EmployeeID FROM Orders;
🌈 SELECT ProductID, Price, Price / 2 AS '50% SalePrice' FROM Products;
🌈 SELECT FALSE, !TRUE, NOT 1, TRUE, !FALSE, NOT FALSE;
🌈 SELECT 0 = TRUE, 1 = FALSE, 1 = TRUE, 0 = FALSE;
🌈 SELECT * FROM Customers WHERE TRUE;
🌈 SELECT * FROM Customers WHERE FALSE;
아무 데이터도 가져오지 않습니다.
where 조건이 참인 경우만 데이터를 가져오는 것을 알 수 있습니다.
🌈 SELECT * FROM Customers WHERE Country = 'Germany';
🌈 SELECT TRUE IS TRUE, TRUE IS NOT TRUE;
IS: 양쪽이 모두 TRUE이거나 FALSE면 결과는 참이 됩니다.
IS NOT: 한쪽은 TRUE이고 한쪽은 FALSE면 결과는 참이 됩니다.
🌈 SELECT (TRUE IS TRUE) IS FALSE;
🌈 SELECT 1 + 1 = 2 OR 1 + 1 = 3;
OR: 양쪽의 값 중 1개만 TRUE여도 결과는 TRUE가 됩니다.
따라서 결과는 TRUE가 됩니다.
🌈 SELECT 1 + 1 = 2 AND 1 + 1 = 3;
AND: 양쪽의 값 모두가 TRUE일 때 결과는 TRUE가 됩니다.
따라서 결과는 FALSE가 됩니다.
🌈 SELECT * FROM Customers WHERE City = 'Berlin' AND Country = 'Germany';
🌈 SELECT * FROM Customers WHERE City = 'Berlin' OR Country = 'Germany';
🌈 SELECT * FROM Orders WHERE CustomerID = 65 AND (EmployeeID = 6 OR ShipperID = 2);
CustomerID가 65"이면서", (EmployeeID가 6"이거나" ShipperID가 2인 값)만 TRUE가 됩니다.
❗️괄호가 없다면 왼쪽부터 순서대로 연산하기 때문에 다른 결과가 나옵니다.
- CustomerID가 65"이면서" EmployeeID가 6"이거나", ShipperID가 2인 값이 TRUE가 됩니다.
🌈 SELECT 1 = 1, 1 != 1, 1 <> 1, 1 > 2, 1 < 2, 1 >= 2, 1 <= 2;
🌈 SELECT ProductName, Price, Price > 20 AS '20달러 넘음' FROM Products;
🌈 SELECT 10 BETWEEN 1 AND 10;
10이 1과 10 사이에 있는 값이면 TRUE가 됩니다.
조건이 1과 10이라면 1과 10도 TRUE에 포함됩니다.
-❗️MySQL의 경우 "10 AND 1"과 같이 큰 숫자를 앞에 쓰면 FALSE가 됩니다.
🌈 SELECT 'boanana' NOT BETWEEN 'apple' AND 'Cola';
알파벳도 BETWEEN 연산자를 사용할 수 있으며 MySQL은 대소문자 구분이 없습니다.
NOT을 넣으면 반대의 의미를 갖습니다.
🌈 SELECT * FROM OrderDetails WHERE Quantity BETWEEN 1 AND 10;
🌈 SELECT 1 + 2 IN (1, 2, 3), 'holla' NOT IN ('cola', 'holla');
IN (...) : 왼쪽 값이 괄호 안 값에 있으면 TRUE
NOT IN (...) : 왼쪽 값이 괄호 안 값에 없으면 TRUE
🌈 SELECT * FROM Customers WHERE Country IN ('Mexico', 'UK');
🌈 SELECT 'holla' LIKE 'HOLLA', 'holla' LIKE 'H%', 'holla' LIKE 'h%a', 'hoLLa' LIKE '%ll%';
LIKE '...%...' : 0~N개의 문자를 가진 패턴
h%의 경우 h 뒤로 0~N개의 문자가 올 수 있다는 의미입니다.
만약 'holla' LIKE '%h'의 경우 h 뒤에 아무것도 오지 않으므로 FALSE가 됩니다.
MySQL은 언제나 대소문자를 가리지 않습니다.
🌈 SELECT * FROM Customers WHERE CustomerName LIKE 'a%';
CustomerName column에서 a로 시작하는 데이터가 TRUE가 되어 가져옵니다.
'%a'였다면 a로 끝나는 데이터만 가져옵니다.
%의 위치가 포인트인 연산자입니다.
🌈 SELECT * FROM Employees WHERE Notes LIKE '%member%';
LIKE + % 연산자는 긴 문자열 데이터에서 특정 문자를 포함하는 데이터를 찾을 때 유용합니다.
조건이 'member%'였다면 member로 시작하는 글만 검색됩니다.
🌈 SELECT 'holla' LIKE '____', 'holla' LIKE 'holl', 'holla' LIKE 'hol_', 'holla' LIKE 'ho_', 'hoLLa' LIKE__ '_oll';
LIKE '..._...' : _(under bar)갯수만큼 문자를 가진 패턴
언더바 5개를 쓰면 5글자인 경우 TRUE가 됩니다.
언더바 갯수가 포인트인 연산자입니다.
🌈 SELECT * FROM Orders WHERE CustomerID LIKE '_3';
💕 참고: 얄코님 유튜브 강의, SQL 첫걸음