예를 들어, Products 테이블과 Suppliers 테이블이 있을 때, 제품 정보와 각 제품을 공급하는 공급업체 정보를 한 번에 조회하고 싶을 때 JOIN을 사용하면 됩니다.
Products
테이블:product_id | product_name | supplier_id | price |
---|---|---|---|
1 | Laptop | 1 | 1000 |
2 | Phone | 2 | 500 |
3 | Tablet | 1 | 800 |
Suppliers
테이블:supplier_id | supplier_name | country |
---|---|---|
1 | Supplier A | USA |
2 | Supplier B | UK |
두 테이블의 공통 키인 supplier_id
를 기준으로 제품과 공급업체 정보를 결합할 수 있습니다.
SELECT Products.product_name, Products.price, Suppliers.supplier_name, Suppliers.country
FROM Products
JOIN Suppliers ON Products.supplier_id = Suppliers.supplier_id;
product_name | price | supplier_name | country |
---|---|---|---|
Laptop | 1000 | Supplier A | USA |
Phone | 500 | Supplier B | UK |
Tablet | 800 | Supplier A | USA |
위의 쿼리는 서로 다른 테이블에서 공통된 값을 기준으로 데이터를 결합하여 하나의 결과로 조회하는 과정을 보여줍니다. JOIN을 통해 다양한 테이블의 데이터를 효율적으로 연결할 수 있습니다! 😊
INNER JOIN
에서 ON 절은 두 테이블을 공통된 값을 기준으로 결합할 때 자주 사용됩니다. 여기서 ON 절은 두 테이블 간의 관계를 명확하게 지정해주는 역할을 하죠.
Employees
테이블:employee_id | employee_name | department_id |
---|---|---|
1 | Alice | 10 |
2 | Bob | 20 |
3 | Charlie | 10 |
Departments
테이블:department_id | department_name |
---|---|
10 | HR |
20 | Sales |
30 | IT |
SELECT Employees.employee_name, Departments.department_name
FROM Employees
INNER JOIN Departments ON Employees.department_id = Departments.department_id;
employee_name | department_name |
---|---|
Alice | HR |
Bob | Sales |
Charlie | HR |
위의 쿼리는 Employees
테이블의 department_id
와 Departments
테이블의 department_id
가 같은 값을 기준으로, 각 직원의 부서를 조회하는 예시입니다.
USING을 사용한 INNER JOIN
은 두 테이블 간에 공통된 열 이름이 있을 때, 그 열을 기준으로 조인 조건을 지정하는 방법입니다. ON 절과 달리, USING은 두 테이블의 열 이름이 동일할 때만 사용할 수 있습니다.
Employees
테이블:employee_id | employee_name | department_id |
---|---|---|
1 | Alice | 10 |
2 | Bob | 20 |
3 | Charlie | 10 |
Departments
테이블:department_id | department_name |
---|---|
10 | HR |
20 | Sales |
30 | IT |
SELECT employee_name, department_name
FROM Employees
INNER JOIN Departments USING (department_id);
employee_name | department_name |
---|---|
Alice | HR |
Bob | Sales |
Charlie | HR |
위의 쿼리는 USING 절을 통해 department_id
컬럼을 기준으로, 두 테이블의 데이터를 결합하는 방법을 보여줍니다. 공통된 컬럼 이름이 있을 때, 더 간결한 방식으로 조인 조건을 지정할 수 있는 장점이 있죠! 😎
JOIN을 사용할 때 ON
과 WHERE
는 각기 다른 역할을 하며, 데이터 필터링 방식에 차이가 있습니다. 두 절의 차이를 명확히 이해하면 더 정확하고 효율적인 쿼리를 작성할 수 있습니다.
ON
은 JOIN할 때 두 테이블을 어떻게 연결할지 정의하는 절입니다.
즉, 테이블을 결합할 기준이 되는 조건을 설정하는 역할을 합니다.
SELECT *
FROM employees e
JOIN departments d ON e.department_id = d.department_id;
이 쿼리는 employees
테이블과 departments
테이블을 department_id
로 연결합니다.
WHERE
는 JOIN 이후의 결과에서 특정 조건을 만족하는 데이터를 필터링하는 데 사용됩니다.
즉, JOIN 후의 데이터를 추가로 걸러내는 역할을 합니다.
SELECT *
FROM employees e
JOIN departments d ON e.department_id = d.department_id
WHERE e.salary > 5000;
위 쿼리는 employees
와 departments
를 JOIN한 후, salary
가 5,000 이상인 직원만 필터링합니다.
LEFT JOIN에서는 ON
과 WHERE
의 차이가 더 뚜렷해집니다:
ON 절에서 필터링:
SELECT *
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id AND d.location = 'Seoul';
LEFT JOIN
으로 모든 직원을 포함하며, 부서의 위치가 Seoul
인 경우만 매칭됩니다.WHERE 절에서 필터링:
SELECT *
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
WHERE d.location = 'Seoul';
LEFT JOIN
결과 중 Seoul
에 해당하는 데이터만 남고, 나머지는 제외됩니다.NATURAL JOIN은 두 테이블에서 동일한 이름을 가진 모든 열을 자동으로 조인 조건으로 삼아 조인을 수행하는 방식입니다. ON이나 USING 절을 명시하지 않아도 동일한 열 이름이 있을 경우 자동으로 해당 열을 기준으로 데이터를 결합해줍니다.
Employees
테이블:employee_id | employee_name | department_id |
---|---|---|
1 | Alice | 10 |
2 | Bob | 20 |
3 | Charlie | 10 |
Departments
테이블:department_id | department_name |
---|---|
10 | HR |
20 | Sales |
30 | IT |
SELECT employee_name, department_name
FROM Employees
NATURAL JOIN Departments;
employee_name | department_name |
---|---|
Alice | HR |
Bob | Sales |
Charlie | HR |
department_id
라는 동일한 열을 자동으로 기준으로 잡아, 두 테이블의 데이터를 결합했습니다.
두 테이블 Students와 Classes가 class_id
를 기준으로 조인해야 하는데, 두 테이블 모두 year
라는 공통 열도 가지고 있어 NATURAL JOIN을 사용할 경우 의도치 않게 year
열도 포함되어 조인됩니다.
Students
테이블:student_id | student_name | class_id | year |
---|---|---|---|
1 | Alice | 101 | 2023 |
2 | Bob | 102 | 2022 |
3 | Charlie | 101 | 2022 |
Classes
테이블:class_id | class_name | year |
---|---|---|
101 | Math | 2023 |
102 | Science | 2023 |
103 | History | 2022 |
SELECT s.student_id, s.student_name, c.class_name
FROM Students s
NATURAL JOIN Classes c;
student_id | student_name | class_name |
---|---|---|
1 | Alice | Math |
class_id
뿐만 아니라 공통된 열인 year
도 자동으로 조인 조건에 포함되기 때문에, 두 열 모두 일치해야 조인이 성립됩니다.class_id = 101
과 year = 2023
으로 일치하여 조회되었습니다.class_id = 101
이 맞지만 year = 2022
이기 때문에 결과에서 제외되었습니다.class_id = 102
이 맞지만 year = 2022
라서 Classes
테이블의 year = 2023
과 일치하지 않아 결과에 포함되지 않았습니다.이 문제를 해결하려면 NATURAL JOIN 대신 ON 절을 사용하여 원하는 열(class_id
)만을 기준으로 명확하게 조인 조건을 지정해 주어야 합니다.
SELECT s.student_id, s.student_name, c.class_name
FROM Students s
JOIN Classes c ON s.class_id = c.class_id;
이렇게 ON 절을 사용하여 class_id만을 기준으로 명확하게 지정하면, year 열이 조인 조건에 포함되지 않아, 의도한 대로 데이터를 조회할 수 있습니다. 😊
LEFT OUTER JOIN은 왼쪽 테이블의 모든 행을 반환하고, 오른쪽 테이블에서 일치하는 데이터가 있을 경우 함께 반환합니다. 오른쪽 테이블에 일치하지 않는 데이터는 NULL로 표시됩니다.
Customers
테이블:customer_id | customer_name |
---|---|
1 | John Doe |
2 | Jane Smith |
3 | Max Payne |
Orders
테이블:order_id | customer_id | order_amount |
---|---|---|
101 | 1 | 100 |
102 | 2 | 150 |
SELECT c.customer_name, o.order_amount
FROM Customers c
LEFT JOIN Orders o ON c.customer_id = o.customer_id;
customer_name | order_amount |
---|---|
John Doe | 100 |
Jane Smith | 150 |
Max Payne | NULL |
Max Payne
의 경우 주문이 없지만, LEFT JOIN으로 인해 Customers 테이블의 모든 데이터가 반환되므로, 주문 정보가 없는 경우에는 NULL로 표시됩니다.
RIGHT OUTER JOIN은 오른쪽 테이블의 모든 행을 반환하고, 왼쪽 테이블에서 일치하는 데이터가 있을 경우 함께 반환됩니다. 왼쪽 테이블에 일치하지 않는 데이터는 NULL로 표시됩니다.
Customers
테이블:customer_id | customer_name |
---|---|
1 | John Doe |
2 | Jane Smith |
3 | Max Payne |
Orders
테이블:order_id | customer_id | order_amount |
---|---|---|
101 | 1 | 100 |
102 | 2 | 150 |
103 | 4 | 200 |
SELECT c.customer_name, o.order_amount
FROM Customers c
RIGHT JOIN Orders o ON c.customer_id = o.customer_id;
customer_name | order_amount |
---|---|
John Doe | 100 |
Jane Smith | 150 |
NULL | 200 |
RIGHT JOIN을 사용하여 오른쪽 테이블의 모든 데이터가 반환되고, 일치하지 않는 Customers의 데이터는 NULL로 표시되었습니다. order_id = 103
의 경우, customer_id = 4
는 Customers 테이블에 존재하지 않기 때문에 NULL로 출력되었습니다.
FULL OUTER JOIN은 LEFT JOIN과 RIGHT JOIN의 결과를 합친 것과 같습니다. 양쪽 테이블의 모든 데이터를 포함하고, 일치하지 않는 데이터는 NULL로 반환됩니다.
Customers
테이블:customer_id | customer_name |
---|---|
1 | John Doe |
2 | Jane Smith |
3 | Max Payne |
Orders
테이블:order_id | customer_id | order_amount |
---|---|---|
101 | 1 | 100 |
102 | 2 | 150 |
103 | 4 | 200 |
SELECT c.customer_name, o.order_amount
FROM Customers c
FULL OUTER JOIN Orders o ON c.customer_id = o.customer_id;
customer_name | order_amount |
---|---|
John Doe | 100 |
Jane Smith | 150 |
Max Payne | NULL |
NULL | 200 |
Max Payne
과 order_id = 103
모두 결과에 포함되며, 서로 일치하지 않는 부분은 NULL로 출력됩니다.
MySQL은 FULL OUTER JOIN을 직접적으로 지원하지 않지만, LEFT JOIN과 RIGHT JOIN을 UNION으로 조합하여 비슷한 결과를 얻을 수 있습니다.
SELECT c.customer_name, o.order_amount
FROM Customers c
LEFT JOIN Orders o ON c.customer_id = o.customer_id
UNION
SELECT c.customer_name, o.order_amount
FROM Customers c
RIGHT JOIN Orders o ON c.customer_id = o.customer_id;
이 방법으로 MySQL에서도 FULL OUTER JOIN과 유사한 결과를 만들어낼 수 있습니다! 😊
SELF JOIN은 같은 테이블을 스스로 조인하는 방식으로, 하나의 테이블을 두 개의 다른 집합처럼 취급하여 테이블 내에서 특정한 관계를 찾을 때 사용됩니다. 이는 주로 계층적 구조나 상호 참조 관계를 처리할 때 유용합니다.
회사의 Employees
테이블에서 각 직원의 상사(관리자)를 찾고 싶다고 가정해봅시다. 직원과 상사 모두 같은 Employees
테이블에 있으며, 각 직원의 상사 정보는 manager_id
로 기록되어 있습니다.
Employees
테이블:employee_id | employee_name | manager_id |
---|---|---|
1 | John Doe | 3 |
2 | Jane Smith | 3 |
3 | Max Payne | NULL |
4 | Emily Clark | 1 |
여기서 John Doe와 Jane Smith의 상사는 Max Payne이고, Emily Clark의 상사는 John Doe인 상황입니다. Max Payne은 상사가 없기 때문에 manager_id
가 NULL입니다.
SELECT e.employee_name AS employee, m.employee_name AS manager
FROM Employees e
LEFT JOIN Employees m ON e.manager_id = m.employee_id;
이 쿼리에서 Employees
테이블을 두 번 사용하고, 각각에 대해 별칭을 e
와 m
으로 지정하여 서로 다른 역할(직원과 상사)을 부여합니다. LEFT JOIN을 사용하여 상사가 없는 직원도 조회할 수 있습니다.
employee | manager |
---|---|
John Doe | Max Payne |
Jane Smith | Max Payne |
Max Payne | NULL |
Emily Clark | John Doe |
이 결과에서 각 직원이 누구의 관리하에 있는지 알 수 있습니다. 예를 들어, John Doe와 Jane Smith는 Max Payne을 상사로 두고 있으며, Emily Clark은 John Doe를 상사로 두고 있죠. Max Payne은 상사가 없기 때문에 NULL로 표시됩니다.
Non-Equi Join은 테이블 간의 데이터를 조인할 때 = (등호) 대신에 비교 연산자(>, <, >=, <=, != 등)를 사용하는 조인 방식입니다. 일반적인 조인에서는 Primary Key (PK)와 Foreign Key (FK) 관계에 기반한 등호 조인을 사용하지만, Non-Equi Join은 이를 넘어서 범위나 조건에 맞는 데이터를 조인할 수 있게 해줍니다.
고객의 주문 금액에 따라 할인 등급을 적용하는 시스템이 있다고 가정해 봅시다. Non-Equi Join을 사용하여 주문 금액 범위에 맞는 할인 등급을 적용할 수 있습니다.
Orders
테이블 (주문 정보):order_id | customer_id | order_amount |
---|---|---|
1 | 101 | 50 |
2 | 102 | 150 |
3 | 103 | 300 |
4 | 104 | 450 |
Discounts
테이블 (할인 등급):discount_id | min_amount | max_amount | discount_rate |
---|---|---|---|
1 | 0 | 100 | 5% |
2 | 101 | 200 | 10% |
3 | 201 | 400 | 15% |
4 | 401 | 1000 | 20% |
이제 주문 금액에 맞는 할인 등급을 범위로 매칭해보겠습니다. Orders
테이블과 Discounts
테이블을 Non-Equi Join을 사용하여 min_amount
와 max_amount
사이에 해당하는 주문 금액을 찾아서 조인합니다.
SELECT o.order_id, o.order_amount, d.discount_rate
FROM Orders o
JOIN Discounts d
ON o.order_amount BETWEEN d.min_amount AND d.max_amount;
order_id | order_amount | discount_rate |
---|---|---|
1 | 50 | 5% |
2 | 150 | 10% |
3 | 300 | 15% |
4 | 450 | 20% |
이렇게 Non-Equi Join을 활용하면 단순한 일치뿐만 아니라 범위나 조건에 따라 데이터를 유연하게 연결할 수 있습니다. 😊
서브 쿼리(Subquery)는 하나의 쿼리 내에 또 다른 SELECT 문을 작성하는 방식으로, 복잡한 조건을 처리하거나 특정한 데이터를 필터링할 때 사용됩니다. 서브 쿼리는 비교 연산자와 함께 사용되어 외부 쿼리의 조건을 만족시키는 데이터를 제공하는 역할을 하며, 보통 괄호 ()
로 감싸서 작성됩니다.
=
, >
, <
, IN
등)를 사용해 내부 쿼리의 결과를 외부 쿼리와 비교합니다.우리는 제품 테이블에서 주문이 이루어진 적이 있는 제품들만 조회하려고 합니다. 이때 서브 쿼리를 사용하여 주문된 제품을 필터링할 수 있습니다. 즉, Orders
테이블에 있는 product_id
값과 Products 테이블의 product_id
를 비교하여, 주문된 제품만 가져오는 방식입니다.
Products
테이블:product_id | product_name | price |
---|---|---|
1 | Laptop | 1000 |
2 | Phone | 500 |
3 | Tablet | 800 |
4 | Monitor | 300 |
Orders
테이블:order_id | product_id | quantity |
---|---|---|
101 | 1 | 2 |
102 | 2 | 1 |
103 | 1 | 1 |
이제 서브 쿼리를 사용하여 Orders 테이블에 존재하는 product_id
값을 기준으로, Products 테이블에서 해당 제품만 필터링해봅시다.
SELECT product_name, price
FROM Products
WHERE product_id IN (SELECT product_id FROM Orders);
product_name | price |
---|---|
Laptop | 1000 |
Phone | 500 |
product_id
값에 해당하므로 조회됩니다.=
, IN
, EXISTS
등)를 통해 추출할 때.서브 쿼리는 이렇게 복잡한 조건을 처리할 수 있는 강력한 도구입니다. 예를 들어, 특정 조건을 만족하는 데이터를 다른 테이블의 결과와 비교하여 간단하게 조회할 수 있죠! 😊
Nested Subquery는 서브 쿼리가 여러 단계로 중첩된 형태를 말합니다. 즉, 하나의 쿼리 내에 또 다른 쿼리가 있고, 그 안에 또 다른 쿼리가 있을 수 있는 구조를 갖습니다. 이를 통해 복잡한 데이터를 효율적으로 필터링하거나, 특정 조건을 만족하는 데이터를 추출할 수 있습니다.
단일 행 서브쿼리는 서브쿼리의 결과가 단일 행만 반환될 때 사용됩니다. 주로 비교 연산자(=
, >
, <
등)를 사용하여 외부 쿼리와 값을 비교합니다.
고객과 주문 테이블에서 가장 많은 금액을 지불한 고객의 이름을 조회하는 상황입니다.
Customers
테이블:customer_id | customer_name |
---|---|
1 | Alice |
2 | Bob |
3 | Charlie |
Orders
테이블:order_id | customer_id | total_amount |
---|---|---|
101 | 1 | 300 |
102 | 2 | 500 |
103 | 3 | 400 |
SELECT customer_name
FROM Customers
WHERE customer_id = (SELECT customer_id
FROM Orders
ORDER BY total_amount DESC
LIMIT 1);
customer_name |
---|
Bob |
위 쿼리는 가장 큰 주문 금액을 지불한 고객을 찾고, 그 고객의 이름을 출력합니다. Bob이 가장 많은 금액인 500을 지불했으므로, 결과에 표시됩니다.
다중 행 서브쿼리는 서브쿼리의 결과가 여러 행을 반환할 때 사용됩니다. 이 경우 IN, ANY, ALL 등의 연산자를 사용하여 외부 쿼리와 비교할 수 있습니다.
IN 연산자는 서브쿼리에서 반환된 여러 값 중 하나라도 일치하는지를 확인합니다.
SELECT customer_name
FROM Customers
WHERE customer_id IN (SELECT customer_id FROM Orders);
customer_name |
---|
Alice |
Bob |
Charlie |
이 쿼리는 주문을 한 고객들을 조회하는 예시입니다. Orders 테이블에 존재하는 customer_id
값을 IN 연산자로 조회하여 모든 고객이 반환되었습니다.
ANY 연산자는 서브쿼리에서 반환된 값 중 하나라도 외부 쿼리의 조건을 만족하면 참을 반환합니다.
SELECT customer_name
FROM Customers
WHERE customer_id = ANY (SELECT customer_id FROM Orders WHERE total_amount < 500);
customer_name |
---|
Alice |
Charlie |
이 쿼리는 주문 금액이 500보다 작은 고객들을 조회합니다. Alice와 Charlie가 조건에 해당하여 결과로 반환됩니다.
ALL 연산자는 서브쿼리에서 반환된 값 모두를 외부 쿼리가 만족해야 참을 반환합니다.
SELECT customer_name
FROM Customers
WHERE customer_id = ALL (SELECT customer_id FROM Orders WHERE total_amount > 300);
customer_name |
---|
Bob |
Charlie |
이 쿼리는 모든 주문 금액이 300보다 큰 고객들을 조회합니다. Bob과 Charlie는 조건을 모두 만족하므로 결과로 반환됩니다.
다중 열 서브쿼리는 서브쿼리에서 두 개 이상의 열을 반환하며, 주로 튜플 형식으로 비교합니다. IN 또는 EXISTS 연산자를 사용해 여러 열을 한꺼번에 비교할 수 있습니다.
Orders
테이블:order_id | product_id | customer_id | total_amount |
---|---|---|---|
101 | 1 | 201 | 300 |
102 | 2 | 202 | 500 |
103 | 3 | 203 | 400 |
104 | 1 | 204 | 600 |
Returned_Orders
테이블:return_order_id | order_id | product_id | return_reason |
---|---|---|---|
201 | 101 | 1 | Defective |
202 | 102 | 2 | Wrong item |
SELECT order_id, product_id, total_amount
FROM Orders
WHERE (order_id, product_id) IN (SELECT order_id, product_id FROM Returned_Orders);
order_id | product_id | total_amount |
---|---|---|
101 | 1 | 300 |
102 | 2 | 500 |
이 쿼리는 반품된 주문의 주문 ID와 제품 ID가 Orders 테이블과 일치하는 경우를 반환합니다.
이렇게 Nested Subquery를 사용하면 복잡한 데이터를 효율적으로 처리할 수 있습니다! 😊
Inline View는 쿼리의 FROM 절에 서브 쿼리를 사용하여 마치 임시 테이블처럼 데이터를 처리하는 방식입니다. 이 서브 쿼리는 쿼리 실행이 완료되면 사라지며, 물리적으로 데이터베이스에 저장되지 않지만, 외부 쿼리에서 다른 테이블처럼 참조할 수 있습니다. Inline View는 복잡한 쿼리를 간결하게 처리하고, 페이지네이션이나 순위 부여 등의 다양한 용도로 활용됩니다.
다음은 Products 테이블에서 평균 가격보다 비싼 제품들을 조회하는 Inline View 예시입니다. 서브 쿼리를 FROM 절에 사용하여 임시 테이블을 생성한 후, 그 결과를 이용하여 외부 쿼리를 실행합니다.
Products
테이블:product_id | product_name | price |
---|---|---|
1 | Laptop | 1000 |
2 | Phone | 500 |
3 | Tablet | 800 |
SELECT product_name, avg_price
FROM (
SELECT product_name, price, AVG(price) OVER () AS avg_price
FROM Products
) AS Temp
WHERE price > avg_price;
product_name | avg_price |
---|---|
Laptop | 766.67 |
위 쿼리는 Products 테이블에서 제품의 평균 가격을 계산한 후, 그보다 높은 가격을 가진 제품만을 조회하는 예시입니다. Laptop의 가격이 평균 가격보다 높기 때문에 결과에 포함되었습니다.
TOP-N 질의는 특정 조건에 따라 상위 N개의 행을 조회하는 방식입니다. Inline View를 사용하면 동적으로 임시 테이블을 생성하고, 그 안에서 상위 N개의 데이터를 추출할 수 있습니다.
다음 예시는 Products 테이블에서 가장 비싼 상위 5개 제품을 조회하는 방식입니다.
Products
테이블:product_id | product_name | price |
---|---|---|
1 | Laptop | 1000 |
2 | Phone | 500 |
3 | Tablet | 800 |
4 | Monitor | 300 |
5 | Headphones | 200 |
6 | Keyboard | 150 |
7 | Mouse | 100 |
8 | Printer | 400 |
9 | Webcam | 250 |
10 | Desk | 350 |
SELECT b.rn, b.product_id, b.product_name, b.price
FROM (
SELECT @rownum := @rownum + 1 AS rn, a.*
FROM (
SELECT product_id, product_name, price
FROM Products
ORDER BY price DESC
) a, (SELECT @rownum := 0) tmp
) b
WHERE b.rn <= 5;
rn | product_id | product_name | price |
---|---|---|---|
1 | 1 | Laptop | 1000 |
2 | 3 | Tablet | 800 |
3 | 2 | Phone | 500 |
4 | 8 | Printer | 400 |
5 | 10 | Desk | 350 |
위 쿼리는 가격 기준으로 상위 5개의 제품을 조회합니다. @rownum 변수를 사용하여 각 행에 순번을 매기고, 그 순번을 기준으로 상위 5개의 제품을 가져왔습니다.
다음은 페이지네이션을 위해 Inline View와 변수를 사용하여, 2페이지에 해당하는 제품 목록을 동적으로 조회하는 예시입니다. 각 페이지에 5개의 제품만 표시하는 방식입니다.
SET @pageno = 2; -- 페이지 번호 설정
SELECT b.rn, b.product_id, b.product_name, b.price
FROM (
SELECT @rownum := @rownum + 1 AS rn, a.*
FROM (
SELECT product_id, product_name, price
FROM Products
ORDER BY price DESC
) a, (SELECT @rownum := 0) tmp
) b
WHERE b.rn > (@pageno * 5 - 5) AND b.rn <= (@pageno * 5);
rn | product_id | product_name | price |
---|---|---|---|
6 | 6 | Keyboard | 150 |
7 | 9 | Webcam | 250 |
8 | 10 | Desk | 350 |
9 | 8 | Printer | 400 |
10 | 4 | Monitor | 300 |
이 쿼리는 2페이지에 해당하는 6번째부터 10번째까지의 제품을 조회합니다. 각 페이지에는 5개의 제품만 표시되며, 페이지 번호는 @pageno 변수를 사용해 동적으로 변경할 수 있습니다.
LIMIT을 사용하여 특정 범위의 데이터를 페이지 단위로 가져올 수도 있습니다. 다음은 6번째부터 10번째 제품을 조회하는 쿼리입니다.
SELECT a.*
FROM (
SELECT @rownum := @rownum + 1 AS rn, product_id, product_name, price
FROM Products p, (SELECT @rownum := 0) tmp
ORDER BY price DESC
) a
LIMIT 5, 5;
rn | product_id | product_name | price |
---|---|---|---|
6 | 6 | Keyboard | 150 |
7 | 9 | Webcam | 250 |
8 | 10 | Desk | 350 |
9 | 8 | Printer | 400 |
10 | 4 | Monitor | 300 |
이 쿼리는 Inline View와 LIMIT을 결합하여 특정 범위의 데이터를 간결하게 처리하는 예시입니다. 6번째부터 10번째 제품을 반환하는 방식입니다.
Inline View는 다양한 상황에서 유용하게 사용할 수 있는 강력한 도구입니다! 😊
Scalar Subquery는 단일 값을 반환하는 서브 쿼리로, 한 개의 행과 한 개의 열만을 결과로 돌려줍니다. 이 서브 쿼리는 일반적인 값처럼 취급되며, SELECT 문에서 하나의 컬럼처럼 사용할 수 있습니다. 스칼라 서브쿼리는 조건을 정의하거나 특정 값의 계산에 유용하게 사용됩니다.
우리는 Products 테이블에서 각 제품의 가격과 전체 평균 가격을 함께 조회하려고 합니다. 여기서 스칼라 서브쿼리를 사용하여 전체 평균 가격을 계산하고, 각 제품의 가격과 함께 출력합니다.
Products
테이블:product_id | product_name | price |
---|---|---|
1 | Laptop | 1000 |
2 | Phone | 500 |
3 | Tablet | 800 |
4 | Monitor | 300 |
5 | Headphones | 200 |
SELECT product_name, price,
(SELECT AVG(price) FROM Products) AS avg_price
FROM Products;
product_name | price | avg_price |
---|---|---|
Laptop | 1000 | 560.00 |
Phone | 500 | 560.00 |
Tablet | 800 | 560.00 |
Monitor | 300 | 560.00 |
Headphones | 200 | 560.00 |
위 쿼리는 Products 테이블의 각 제품 가격을 출력하면서, 스칼라 서브쿼리를 통해 전체 평균 가격을 계산하여 각 행에 동일한 값으로 표시합니다. 평균 가격 560은 모든 제품에 대해 동일하게 나타납니다.
스칼라 서브쿼리는 다양한 상황에서 사용할 수 있습니다. 다음은 스칼라 서브쿼리를 활용할 수 있는 예시들입니다.
SELECT product_name, price,
CASE WHEN price > (SELECT AVG(price) FROM Products)
THEN 'Above Average'
ELSE 'Below Average'
END AS price_comparison
FROM Products;
product_name | price | price_comparison |
---|---|---|
Laptop | 1000 | Above Average |
Phone | 500 | Below Average |
Tablet | 800 | Above Average |
Monitor | 300 | Below Average |
Headphones | 200 | Below Average |
위 쿼리는 스칼라 서브쿼리를 사용하여 각 제품의 가격이 전체 평균 가격보다 높은지 여부를 판별합니다. Laptop과 Tablet은 평균 가격보다 높아 "Above Average"로 표시되며, 나머지 제품은 "Below Average"로 표시됩니다.
SELECT product_name, price,
(SELECT COUNT(*) FROM Orders WHERE Orders.product_id = Products.product_id) AS order_count
FROM Products;
이 쿼리는 Products 테이블에서 각 제품의 주문 수를 Orders 테이블에서 조회하여 출력합니다.
이처럼 Scalar Subquery는 다양한 상황에서 효율적인 데이터 처리를 가능하게 해주는 강력한 도구입니다! 😊
서브 쿼리는 데이터를 조회하는 데만 사용되는 것이 아니라, CREATE, INSERT, UPDATE, DELETE와 같은 데이터 조작에서도 매우 유용하게 활용됩니다. 서브 쿼리를 사용하면 복잡한 조건을 통해 데이터를 쉽게 필터링하고, 그 결과를 테이블 생성이나 수정에 적용할 수 있습니다.
서브 쿼리를 사용하여 새로운 테이블을 생성할 때, 기존 테이블의 구조나 데이터를 기반으로 새로운 테이블을 만들 수 있습니다.
CREATE TABLE cust_copy
SELECT * FROM Customers;
이 쿼리는 Customers 테이블의 모든 데이터를 cust_copy라는 테이블로 복사하여 동일한 구조와 데이터를 가진 새로운 테이블을 생성합니다.
CREATE TABLE cust_blank
SELECT * FROM Customers
WHERE 1 = 0;
이 쿼리는 Customers 테이블의 구조만을 복사하여 cust_blank 테이블을 생성합니다. WHERE 1 = 0
조건을 사용하여 데이터를 복사하지 않고, 빈 테이블을 생성합니다.
CREATE TABLE big_orders
SELECT customer_id, order_id, total_amount
FROM Orders
WHERE total_amount >= 1000;
이 쿼리는 1000달러 이상의 주문을 한 고객들의 정보를 담은 새로운 테이블 big_orders를 생성합니다.
서브 쿼리는 데이터를 삽입할 때도 매우 유용합니다. 특정 조건에 맞는 데이터를 다른 테이블에 삽입할 수 있습니다.
INSERT INTO cust_blank
SELECT customer_id, first_name, last_name, email
FROM Customers
WHERE customer_id IN (SELECT customer_id FROM Orders WHERE total_amount >= 500);
이 쿼리는 500달러 이상의 주문을 한 고객들의 정보를 cust_blank 테이블에 삽입합니다. 서브 쿼리를 사용해 Orders 테이블에서 조건에 맞는 고객 ID를 추출하고, 이를 기반으로 Customers 테이블에서 해당 고객들의 정보를 가져와 삽입합니다.
서브 쿼리는 데이터를 업데이트할 때도 조건을 세부적으로 설정하는 데 유용합니다.
UPDATE Orders
SET total_amount = total_amount + 100
WHERE total_amount < (SELECT AVG(total_amount) FROM Orders);
이 쿼리는 평균 주문 금액보다 낮은 주문들을 찾아서 100달러씩 인상합니다. 서브 쿼리를 사용해 Orders 테이블의 평균 금액을 계산하고, 이를 기준으로 조건을 설정하여 데이터를 업데이트합니다.
서브 쿼리는 데이터 삭제에도 효과적으로 사용됩니다. 특정 조건에 맞는 데이터를 삭제할 수 있습니다.
DELETE FROM Orders
WHERE total_amount < (SELECT AVG(total_amount) FROM Orders);
이 쿼리는 평균 주문 금액보다 낮은 주문들을 Orders 테이블에서 삭제합니다. 서브 쿼리로 평균 금액을 계산한 후, 그보다 낮은 금액을 가진 행들을 삭제하는 방식입니다.
서브 쿼리는 데이터를 생성, 수정, 삭제할 때 복잡한 조건을 처리하고 유연하게 데이터를 조작할 수 있는 강력한 도구입니다! 😊