MySQL에서 흔히 볼 수 있는 하위 쿼리 문

13053 단어
하나.하위 질의문 형식
  • 기본문법:SELECT 필드 목록/*+FROM+표명+[WHERE 조건];
  • 전체 문법: SELECT [SELECT 옵션] + 필드 목록 [필드 별명]/* + FROM + 데이터 원본 + [WHERE 조건] + [1] + [2] + [3] + [4];
  • [1] = 그룹 by 자문
  • [2] = having 자구
  • [3] = order by 자구
  • [4] = limit 자문

  • 1. SELECT 옵션
  • SELECT 옵션: 검색된 결과에 대한 SELECT 처리 방식
  • ALL: 기본적으로 모든 질의 결과 유지
  • DISTINCT: 무거운 것을 제거하고 검색한 결과의 모든 필드가 같은 기록을 삭제
    mysql> SELECT * FROM my_copy;
    +-------+
    | name  |
    +-------+
    | curry |
    | curry |
    | curry |
    | A     |
    | a     |
    | A     |
    | a     |
    | A     |
    | a     |
    | A     |
    | a     |
    | A     |
    | B     |
    | b     |
    | a     |
    | A     |
    | B     |
    | b     |
    | a     |
    | A     |
    | B     |
    | b     |
    +-------+
    22 rows in set (0.65 sec)
    
    mysql> SELECT ALL * FROM my_
    +-------+
    | name  |
    +-------+
    | curry |
    | curry |
    | curry |
    | A     |
    | a     |
    | A     |
    | a     |
    | A     |
    | a     |
    | A     |
    | a     |
    | A     |
    | B     |
    | b     |
    | a     |
    | A     |
    | B     |
    | b     |
    | a     |
    | A     |
    | B     |
    | b     |
    +-------+
    22 rows in set (0.00 sec)
    
    mysql> SELECT DISTINCT * FROM my_copy;
    +-------+
    | name  |
    +-------+
    | curry |
    | A     |
    | B     |
    +-------+
    3 rows in set (0.09 sec)
    

  • 2. 필드 별칭
  • 필드 별명: 데이터를 조회할 때 필드의 이름이 반드시 수요를 만족시키지 못할 때가 있다(특히 여러 테이블을 조회할 때 동명의 필드가 있을 수 있다). 이럴 때 필드의 이름을 바꾸고 별명을 지어야 한다.
  • 기본 문법: 필드 이름 + [AS] + 별명;
    mysql> SELECT id, name AS   , age AS   , grade AS   
        -> FROM student;
    +----+--------+------+------+
    | id |      |    |    |
    +----+--------+------+------+
    |  1 | curry  |   30 |  3.1 |
    |  2 | durant |   29 |  3.4 |
    |  3 | Riuo   |   27 |  3.6 |
    |  4 | harden |   29 |  3.2 |
    +----+--------+------+------+
    4 rows in set (0.13 sec)
    

  • 3. 데이터 소스
  • 데이터 원본: 데이터의 원본, 관계형 데이터베이스의 데이터 원본은 모두 데이터 테이블이고 본질적으로 데이터가 2차원 테이블과 유사하기만 하면 최종적으로 데이터 원본이 될 수 있다.데이터 원본은 세 가지로 나뉘는데 그것이 바로 단일 테이블 데이터 원본, 다중 테이블 데이터 원본과 조회 문장이다.
  • 단일 테이블 데이터 소스: SELECT*FROM+테이블 이름;
    mysql> SELECT * FROM student;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  1 | curry  |   30 |   3.1 |     |    1 |
    |  2 | durant |   29 |   3.4 |     |    1 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 |
    |  4 | harden |   29 |   3.2 |     |    1 |
    +----+--------+------+-------+------+------+
    4 rows in set (0.00 sec)
    
  • 다중 표 데이터 원본: SELECT*FROM+표 1명, 표 2명,....
    mysql> SELECT * FROM student, my_class;
    +----+--------+------+-------+------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id | grade | room | id   |
    +----+--------+------+-------+------+------+-------+------+------+
    |  1 | curry  |   30 |   3.1 |     |    1 | 101   | S    |    2 |
    |  1 | curry  |   30 |   3.1 |     |    1 | 102   | B    |    2 |
    |  1 | curry  |   30 |   3.1 |     |    1 | 103   | D    |    2 |
    |  2 | durant |   29 |   3.4 |     |    1 | 101   | S    |    2 |
    |  2 | durant |   29 |   3.4 |     |    1 | 102   | B    |    2 |
    |  2 | durant |   29 |   3.4 |     |    1 | 103   | D    |    2 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 | 101   | S    |    2 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 | 102   | B    |    2 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 | 103   | D    |    2 |
    |  4 | harden |   29 |   3.2 |     |    1 | 101   | S    |    2 |
    |  4 | harden |   29 |   3.2 |     |    1 | 102   | B    |    2 |
    |  4 | harden |   29 |   3.2 |     |    1 | 103   | D    |    2 |
    +----+--------+------+-------+------+------+-------+------+------+
    12 rows in set (0.00 sec)
    
  • 다중 테이블 데이터 원본을 사용할 때 기본적으로 한 테이블에서 한 기록을 꺼내서 다른 테이블에서 모든 기록과 일치하게 하고 모두 보존하면 저장 공간을 낭비하기 때문에 최대한 피해야 합니다!
  • 조회문구(하위 조회): SELECT*FROM+(SELECT*FROM표명)+[AS]별명;
    mysql> SELECT * FROM (SELECT * FROM student) AS stu;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  1 | curry  |   30 |   3.1 |     |    1 |
    |  2 | durant |   29 |   3.4 |     |    1 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 |
    |  4 | harden |   29 |   3.2 |     |    1 |
    +----+--------+------+-------+------+------+
    4 rows in set (0.05 sec)
    

  • 4.WHERE 자구
  • WHERE 자구: 데이터를 판단하고 선별하는 데 사용되며 되돌아오는 결과는 0 또는 1이다. 그 중에서 0은false,1은true,where는 디스크에서 데이터를 직접 얻을 때부터 판단하는 유일한 조건이다. 디스크에서 데이터를 읽으면 where판단을 시작하고 판단 결과가 진실이면 유지한다.반대로 저장하지 않습니다.
  • 판단조건:
         :> < >= <= <> = like between and in not in
         :&& || !
    
  • 실례1은 다음과 같다.
    mysql> SELECT * FROM student
        -> WHERE id = 2 || id = 3;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  2 | durant |   29 |   3.4 |     |    1 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 |
    +----+--------+------+-------+------+------+
    2 rows in set (0.00 sec)
    
    mysql> SELECT * FROM student
        -> WHERE id IN(2,3);
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  2 | durant |   29 |   3.4 |     |    1 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 |
    +----+--------+------+-------+------+------+
    2 rows in set (0.00 sec)
    
  • 실례 2: 학생에서 id가 1에서 3 사이의 기록을 조회합니다.주의:between and를 사용할 때 선택한 구간은 폐구간, 즉 단점값을 포함합니다.또한 and 앞의 수치는 반드시 and 뒤의 수치보다 커야 합니다. 그렇지 않으면 빈 판단이 나타납니다!
    mysql> SELECT * FROM student
        -> WHERE id BETWEEN 1 AND 3;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  1 | curry  |   30 |   3.1 |     |    1 |
    |  2 | durant |   29 |   3.4 |     |    1 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 |
    +----+--------+------+-------+------+------+
    3 rows in set (0.03 sec)
    

  • 5.group by 자구
  • group by 자문: 표의 어떤 필드에 따라 그룹을 나눈다. 즉, 같은 필드 값을 포함하는 기록을 한 그룹에 놓고 다른 것은 다른 그룹에 놓는다.
  • 기본 문법: 그룹 by + 필드 이름;
  • 실례: 표student의 데이터를 필드sex에 따라 그룹
    mysql> SELECT * FROM student
        -> GROUP BY sex;
    +----+-------+------+-------+------+------+
    | id | name  | age  | grade | sex  | c_id |
    +----+-------+------+-------+------+------+
    |  3 | Riuo  |   27 |   3.6 |     |    1 |
    |  1 | curry |   30 |   3.1 |     |    1 |
    +----+-------+------+-------+------+------+
    2 rows in set (0.02 sec)
    
  • 표student가 그룹을 나눈 후에 데이터가 분실되었습니다!실제로는 그렇지 않다. 그룹 by가 그룹을 나누는 목적은 (그룹 필드에 따라) 통계 데이터를 집계하기 위한 것이지 단순히 그룹을 나누기 위한 것이 아니다.SQL은 통계 작성을 용이하게 하기 위해 다음과 같은 일련의 통계 함수를 제공합니다.
  • count(): 그룹을 집계한 후 각 그룹의 총 기록수;
  • count() 함수에서는 다음 두 가지 매개변수를 사용할 수 있습니다.
  • *: 통계 그룹 내 전체 레코드 수
  • 필드 이름: 대응하는 필드의 비null(어떤 기록에서 이 필드의 값이null이면 통계하지 않음) 기록된 총 수량

  • max(): 각 그룹의 최대치를 통계한다.
  • min(): 각 그룹의 최소값을 통계한다.
  • avg(): 각 그룹의 평균치를 통계한다.
  • sum(): 각 그룹의 데이터 총계를 통계한다.

  • 실례: 표student의 데이터를 필드sex에 따라 그룹으로 나누고 통계
    mysql> SELECT sex, COUNT(*), MAX(age), MIN(age), SUM(age)
        -> FROM student
        -> GROUP BY sex;
    +------+----------+----------+----------+----------+
    | sex  | COUNT(*) | MAX(age) | MIN(age) | SUM(age) |
    +------+----------+----------+----------+----------+
    |     |        1 |       27 |       27 |       27 |
    |     |        3 |       30 |       29 |       88 |
    +------+----------+----------+----------+----------+
    2 rows in set (0.09 sec)
    
  • 그룹 by를 사용하여 그룹을 나눈 후 표시된 기록은 그룹의 필드 값에 따라 정렬됩니다. 기본값은 승차순입니다. 인위적으로 승차순과 강차를 설정할 수도 있습니다.기본 문법: 그룹 by + 필드 이름 + [desc/asc];
    mysql> SELECT sex, COUNT(*)
        -> FROM student
        -> GROUP BY sex DESC;
    +------+----------+
    | sex  | COUNT(*) |
    +------+----------+
    |     |        3 |
    |     |        1 |
    +------+----------+
    2 rows in set (0.00 sec)
    
  • 위의 테스트 샘플 중 한 필드로 그룹을 나눈다.실제로 다중 필드를 사용하여 그룹을 구성할 수도 있습니다. 즉, 한 필드에 따라 그룹을 구성한 다음 그룹화된 결과를 다른 필드(이 필드가 포함된 경우)로 다시 그룹화할 수도 있습니다.
  • 실례: 표student의 데이터를 필드grade에 따라 그룹을 나누고 필드sex에 따라 그룹을 나눈다
    mysql> SELECT *, COUNT(*) FROM student
        -> GROUP BY grade, sex;
    +----+--------+------+-------+------+------+----------+
    | id | name   | age  | grade | sex  | c_id | COUNT(*) |
    +----+--------+------+-------+------+------+----------+
    |  1 | curry  |   30 |   3.1 |     |    1 |        1 |
    |  4 | harden |   29 |   3.2 |     |    1 |        1 |
    |  2 | durant |   29 |   3.4 |     |    1 |        1 |
    |  3 | Riuo   |   27 |   3.6 |     |    1 |        1 |
    +----+--------+------+-------+------+------+----------+
    4 rows in set (0.00 sec)
    
  • 함수 groupconcat (필드 이름) 은 그룹의 결과에 있는 필드 값을 문자열로 연결할 수 있습니다. 즉, 그룹의 필드 값을 모두 보존할 수 있습니다.실례: 테이블student의 데이터를 필드 sex에 따라 그룹화하고 필드name의 값
    mysql> SELECT sex, age, count(*), group_concat(name)
        -> FROM student
        -> group by sex;
    +------+------+----------+---------------------+
    | sex  | age  | count(*) | group_concat(name)  |
    +------+------+----------+---------------------+
    |     |   27 |        1 | Riuo                |
    |     |   30 |        3 | curry,durant,harden |
    +------+------+----------+---------------------+
    2 rows in set (0.06 sec)
    
  • 을 보존합니다.
  • 거슬러 올라가는 통계: withrollup 키워드(SQL 문장 끝에 쓰기)를 이용하여 매번 그룹을 나눈 후 현재 그룹의 필드에 따라 통계하고 상급 그룹에 보고할 수 있다.역추적 통계를 진행할 때 그룹 필드를 비웁니다.예:
    mysql> SELECT sex, count(*) FROM student
        -> group by sex with rollup;
    +------+----------+
    | sex  | count(*) |
    +------+----------+
    |     |        1 |
    |     |        3 |
    | NULL |        4 |
    +------+----------+
    3 rows in set (0.00 sec)
    
  • 6.having 자구
  • having자구:where자구와 마찬가지로 조건판단을 한다.그러나where 자구는 디스크 데이터에 대한 판단이고 데이터가 메모리에 들어간 후에 그룹 by 그룹 작업이 진행되며 그룹 결과는 having 자구가 처리해야 한다.따라서 having은where가 할 수 있는 거의 모든 일을 할 수 있지만where는having이 할 수 있는 많은 일을 할 수 없다.
  • 6.1: 그룹 통계의 결과 또는 통계 함수는having만 사용할 수 있다
  • 실례: 표student에서 모든 학급의 인원이 1과 같은 학급
    mysql> SELECT grade, COUNT(*)
        -> FROM student
        -> GROUP BY grade
        -> HAVING COUNT(*) = 1;
    +-------+----------+
    | grade | COUNT(*) |
    +-------+----------+
    |   3.1 |        1 |
    |   3.2 |        1 |
    |   3.4 |        1 |
    |   3.6 |        1 |
    +-------+----------+
    4 rows in set (0.00 sec)
    
  • 을 구한다.
  • 6.2:having은 필드의 별명을 사용할 수 있지만where는 디스크에서 데이터를 읽기 때문에where는 필드의 이름만 사용할 수 있고 별명은 데이터(필드)가 메모리에 들어간 후에만 생길 수 있기 때문이다.
  • 실례: 표student에서 모든 학급의 인원이 1과 같은 학급
    mysql> SELECT grade, COUNT(*) AS total
        -> FROM student
        -> GROUP BY grade
        -> HAVING total = 1;
    +-------+-------+
    | grade | total |
    +-------+-------+
    |   3.1 |     1 |
    |   3.2 |     1 |
    |   3.4 |     1 |
    |   3.6 |     1 |
    +-------+-------+
    4 rows in set (0.00 sec)
    
  • 을 구한다.
    7.order by 자구
  • order by 자구: 어떤 필드에 따라 오름차순 또는 내림차순 정렬, 기본 문법:order by + [asc/desc];
    mysql> SELECT *
        -> FROM student
        -> ORDER BY age;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  3 | Riuo   |   27 |   3.6 |     |    1 |
    |  2 | durant |   29 |   3.4 |     |    1 |
    |  4 | harden |   29 |   3.2 |     |    1 |
    |  1 | curry  |   30 |   3.1 |     |    1 |
    +----+--------+------+-------+------+------+
    4 rows in set (0.00 sec)
    
  • 다중 필드 정렬: 먼저 한 필드에 따라 정렬한 다음에 정렬한 결과에 따라 한 필드에 따라 정렬한다.표student의 데이터를 먼저 연령age승차순으로 배열한 다음에 반grade강차순으로 배열한다.
    mysql> SELECT *
        -> FROM student
        -> ORDER BY age,grade DESC;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  3 | Riuo   |   27 |   3.6 |     |    1 |
    |  2 | durant |   29 |   3.4 |     |    1 |
    |  4 | harden |   29 |   3.2 |     |    1 |
    |  1 | curry  |   30 |   3.1 |     |    1 |
    +----+--------+------+-------+------+------+
    4 rows in set (0.00 sec)
    

  • 8.Limit 자구
  • limit 자문: 결과를 제한하는 문장으로 결과의 수량을 제한한다.
  • 문법: LIMIT + [offset,] + length;
  • 8.1: 길이(데이터량)만 제한
    mysql> SELECT * FROM student LIMIT 2;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  1 | curry  |   30 |   3.1 |     |    1 |
    |  2 | durant |   29 |   3.4 |     |    1 |
    +----+--------+------+-------+------+------+
    2 rows in set (0.00 sec)
    
  • 8.2: 시작값 제한, 길이 제한
    mysql> SELECT * FROM student LIMIT 0, 2;
    +----+--------+------+-------+------+------+
    | id | name   | age  | grade | sex  | c_id |
    +----+--------+------+-------+------+------+
    |  1 | curry  |   30 |   3.1 |     |    1 |
    |  2 | durant |   29 |   3.4 |     |    1 |
    +----+--------+------+-------+------+------+
    2 rows in set (0.00 sec)
    
  • 8.3: 주로 데이터의 페이지를 실현하는데 사용자의 시간을 절약하고 서버의 응답 효율을 향상시키며 자원의 낭비를 줄이는 데 목적이 있다.
  • 좋은 웹페이지 즐겨찾기