수색…
소개
SELECT
는 하나 이상의 테이블에서 선택된 행을 검색하는 데 사용됩니다.
통사론
SELECT DISTINCT [expressions] FROM TableName [WHERE 조건]; /// 단순 선택
SELECT DISTINCT (a), b ...는 SELECT DISTINCT a, b와 같습니다.
SELECT [모두 | DISTINCT | DISTINCTROW] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT | SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] 식 FROM 테이블 [WHERE 조건] [GROUP BY 식] [HAVING 조건] [ORDER BY 식 [ASC | DESC]] [LIMIT [offset_value] number_rows | LIMIT number_rows OFFSET offset_value] [프로 시저 프로 시저 _ 이름] [INTO [OUTFILE 'file_name'옵션 | DUMPFILE 'file_name'| @ variable1, @ variable2, ... @variable_n] [FOR UPDATE | LOCK IN SHARE MODE]; /// 전체 선택 구문
비고
MySQL의 SELECT
문에 대한 자세한 내용은 MySQL 문서를 참조하십시오.
열 이름 별 선택
CREATE TABLE stack(
id INT,
username VARCHAR(30) NOT NULL,
password VARCHAR(30) NOT NULL
);
INSERT INTO stack (`id`, `username`, `password`) VALUES (1, 'Foo', 'hiddenGem');
INSERT INTO stack (`id`, `username`, `password`) VALUES (2, 'Baa', 'verySecret');
질문
SELECT id FROM stack;
결과
+------+
| id |
+------+
| 1 |
| 2 |
+------+
모든 열 선택 (*)
질문
SELECT * FROM stack;
결과
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | admin | admin |
| 2 | stack | stack |
+------+----------+----------+
2 rows in set (0.00 sec)
다음을 수행하여 조인에서 한 테이블의 모든 열을 선택할 수 있습니다.
SELECT stack.* FROM stack JOIN Overflow ON stack.id = Overflow.id;
모범 사례 행을 디버깅하거나 연관 배열로 페치하지 않는 한 *
사용하지 마십시오. 그렇지 않으면 스키마 변경 (ADD / DROP / 열 재 배열)으로 인해 응용 프로그램 오류가 발생할 수 있습니다. 또한 결과 집합에 필요한 열의 목록을 제공하면 MySQL의 쿼리 계획자는 종종 쿼리를 최적화 할 수 있습니다.
장점 :
- 열을 추가 / 제거 할 때
SELECT *
사용한 위치를 변경할 필요가 없습니다. - 쓰기가 더 짧다.
- 또한 답을 볼 수 있으므로
SELECT *
-usage가 정당화 될 수 있습니까?
단점 :
- 필요한 것보다 많은 데이터를 반환하고 있습니다. 행 당 200k를 포함하는 VARBINARY 열을 추가한다고합시다. 하나의 레코드에 대해서만이 데이터가 필요합니다 -
SELECT *
를 사용하면 필요없는 10 개의 행당 2MB를 반환 할 수 있습니다 - 사용 된 데이터에 대한 명시 적
- 열을 지정하면 열 제거시 오류가 발생합니다.
- 쿼리 프로세서는 더 많은 작업을 수행해야합니다 - 테이블에 어떤 열이 있는지 파악합니다 (감사합니다 @vinodadhikary).
- 열이 더 쉽게 사용되는 위치를 찾을 수 있습니다.
- SELECT *를 사용하면 조인의 모든 열을 가져옵니다.
- 서수 참조는 안전하게 사용할 수 없습니다 (열에 대한 서수 참조는 그 자체로 나쁜 습관입니다)
-
TEXT
필드가있는 복잡한 쿼리에서 최적이 아닌 임시 테이블 처리로 인해 쿼리가 느려질 수 있습니다.
WHERE가있는 SELECT
질문
SELECT * FROM stack WHERE username = "admin" AND password = "admin";
결과
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | admin | admin |
+------+----------+----------+
1 row in set (0.00 sec)
WHERE 절에서 중첩 된 SELECT를 사용하여 쿼리
WHERE
절은 더 복잡한 조회를 작성하기 위해 유효한 SELECT
.을 포함 할 수 있습니다. 이것은 '중첩 된'쿼리입니다.
질문
중첩 된 쿼리는 일반적으로 비교를 위해 쿼리에서 단일 원자 값을 반환하는 데 사용됩니다.
SELECT title FROM books WHERE author_id = (SELECT id FROM authors WHERE last_name = 'Bar' AND first_name = 'Foo');
이메일 주소가없는 모든 사용자 이름을 선택합니다.
SELECT * FROM stack WHERE username IN (SELECT username FROM signups WHERE email IS NULL);
면책 조항 : 전체 결과 집합을 비교할 때 성능 향상을 위해 조인 을 사용하는 것을 고려하십시오.
좋아하는 선택 (%)
CREATE TABLE stack
( id int AUTO_INCREMENT PRIMARY KEY,
username VARCHAR(100) NOT NULL
);
INSERT stack(username) VALUES
('admin'),('k admin'),('adm'),('a adm b'),('b XadmY c'), ('adm now'), ('not here');
어디서나 "adm":
SELECT * FROM stack WHERE username LIKE "%adm%";
+----+-----------+
| id | username |
+----+-----------+
| 1 | admin |
| 2 | k admin |
| 3 | adm |
| 4 | a adm b |
| 5 | b XadmY c |
| 6 | adm now |
+----+-----------+
"adm"으로 시작합니다.
SELECT * FROM stack WHERE username LIKE "adm%";
+----+----------+
| id | username |
+----+----------+
| 1 | admin |
| 3 | adm |
| 6 | adm now |
+----+----------+
"adm"으로 끝남 :
SELECT * FROM stack WHERE username LIKE "%adm";
+----+----------+
| id | username |
+----+----------+
| 3 | adm |
+----+----------+
LIKE
절의 %
문자가 임의의 수의 문자와 일치하는 것처럼 _
문자는 한 문자와 일치합니다. 예를 들어,
SELECT * FROM stack WHERE username LIKE "adm_n";
+----+----------+
| id | username |
+----+----------+
| 1 | admin |
+----+----------+
성능 노트 username
인덱스가있는 경우
-
LIKE 'adm'
은`= 'adm' -
LIKE 'adm%
는BETWEEN..AND..
와 유사한'범위 '입니다. 열의 색인을 잘 활용할 수 있습니다. -
LIKE '%adm'
(또는 선도적 인 와일드 카드 어떤 변형) 어떤 인덱스를 사용할 수 없습니다. 그러므로 그것은 느릴 것입니다. 행이 많은 테이블에서는 너무 느려서 쓸모가 없습니다. -
RLIKE
(REGEXP
)는LIKE
보다 느린 경향이 있지만 더 많은 기능이 있습니다. - MySQL이 제공하는 동안
FULLTEXT
테이블과 컬럼의 많은 종류에 색인을, 그FULLTEXT
인덱스를 사용하여 쿼리를 수행하는 데 사용되지 않습니다LIKE
.
별칭 (AS)이있는 SELECT
SQL 별칭은 테이블이나 열의 임시 이름을 바꾸는 데 사용됩니다. 일반적으로 가독성을 높이기 위해 사용됩니다.
질문
SELECT username AS val FROM stack;
SELECT username val FROM stack;
(참고 : AS
는 구문 적으로 선택 사항입니다.)
결과
+-------+
| val |
+-------+
| admin |
| stack |
+-------+
2 rows in set (0.00 sec)
LIMIT 절이있는 SELECT
질문:
SELECT *
FROM Customers
ORDER BY CustomerID
LIMIT 3;
결과:
고객 ID | 고객 이름 | 담당자 이름 | 주소 | 시티 | 우편 번호 | 국가 |
---|---|---|---|---|---|---|
1 | 알프레드 Futterkiste | 마리아 앤더스 | Obere Str. 57 번 | 베를린 | 12209 | 독일 |
2 | Ana Trujillo Emparedados y helados | 아나 트루 질로 | Avda. 드 라 콘 스티 치온 2222 | 멕시코 DF | 05021 | 멕시코 |
삼 | 안토니오 모레노 타 케리아 | 안토니오 모레노 | Mataderos 2312 | 멕시코 DF | 05023 | 멕시코 |
모범 사례 LIMIT
사용할 때는 항상 ORDER BY
를 사용하십시오. 그렇지 않으면 얻을 수있는 행은 예측할 수 없게됩니다.
질문:
SELECT *
FROM Customers
ORDER BY CustomerID
LIMIT 2,1;
설명:
LIMIT
절이 두 개의 숫자를 포함하면 LIMIT offset,count
로 해석됩니다. 따라서이 예에서 쿼리는 두 개의 레코드를 건너 뛰고 하나를 반환합니다.
결과:
고객 ID | 고객 이름 | 담당자 이름 | 주소 | 시티 | 우편 번호 | 국가 |
---|---|---|---|---|---|---|
삼 | 안토니오 모레노 타 케리아 | 안토니오 모레노 | Mataderos 2312 | 멕시코 DF | 05023 | 멕시코 |
노트 :
LIMIT
절의 값은 상수 여야합니다. 열 값이 아닐 수도 있습니다.
DISTINCT가있는 SELECT
SELECT
후 DISTINCT
절은 결과 집합에서 중복 행을 제거합니다.
CREATE TABLE `car`
( `car_id` INT UNSIGNED NOT NULL PRIMARY KEY,
`name` VARCHAR(20),
`price` DECIMAL(8,2)
);
INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (1, 'Audi A1', '20000');
INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (2, 'Audi A1', '15000');
INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (3, 'Audi A2', '40000');
INSERT INTO CAR (`car_id`, `name`, `price`) VALUES (4, 'Audi A2', '40000');
SELECT DISTINCT `name`, `price` FROM CAR;
+---------+----------+
| name | price |
+---------+----------+
| Audi A1 | 20000.00 |
| Audi A1 | 15000.00 |
| Audi A2 | 40000.00 |
+---------+----------+
DISTINCT
는 모든 열에서 작동하여 개별 열이 아닌 결과를 제공합니다. 후자는 종종 새로운 SQL 개발자를 오해합니다. 즉, 열 수준의 뚜렷 함이 아니라 결과 집합의 행 수준에서 중요한 점입니다. 이것을 시각화하려면 위 결과 세트에서 "Audi A1"을보십시오.
최신 버전의 MySQL의 경우 DISTINCT
는 ORDER BY
와 함께 사용할 때와 관련이 있습니다. ONLY_FULL_GROUP_BY
대한 설정은 다음 MySQL 매뉴얼 페이지 ( GROUP BY의 MySQL 처리) 에서 볼 수 있습니다.
좋아하는 선택 (_)
LIKE
절 패턴의 _
문자는 단일 문자와 일치합니다.
질문
SELECT username FROM users WHERE users LIKE 'admin_';
결과
+----------+
| username |
+----------+
| admin1 |
| admin2 |
| admin- |
| adminA |
+----------+
CASE 또는 IF로 선택
질문
SELECT st.name,
st.percentage,
CASE WHEN st.percentage >= 35 THEN 'Pass' ELSE 'Fail' END AS `Remark`
FROM student AS st ;
결과
+--------------------------------+
| name | percentage | Remark |
+--------------------------------+
| Isha | 67 | Pass |
| Rucha | 28 | Fail |
| Het | 35 | Pass |
| Ansh | 92 | Pass |
+--------------------------------+
또는 IF
SELECT st.name,
st.percentage,
IF(st.percentage >= 35, 'Pass', 'Fail') AS `Remark`
FROM student AS st ;
주의
IF(st.percentage >= 35, 'Pass', 'Fail')
즉, IF st.percentage> = 35가 TRUE 이면
'Pass'
를 반환 합니다. ELSE는'Fail'
반환합니다.
선택 사항과 함께 선택
BETWEEN 절을 사용하여 "보다 크고 같음보다 작음"조건의 조합을 바꿀 수 있습니다.
데이터
+----+-----------+
| id | username |
+----+-----------+
| 1 | admin |
| 2 | root |
| 3 | toor |
| 4 | mysql |
| 5 | thanks |
| 6 | java |
+----+-----------+
연산자로 쿼리
SELECT * FROM stack WHERE id >= 2 and id <= 5;
BETWEEN과 (과) 유사한 검색어
SELECT * FROM stack WHERE id BETWEEN 2 and 5;
결과
+----+-----------+
| id | username |
+----+-----------+
| 2 | root |
| 3 | toor |
| 4 | mysql |
| 5 | thanks |
+----+-----------+
4 rows in set (0.00 sec)
노트
BETWEEN은
>=
및<=
, not>
및<
합니다.
NOT BETWEEN 사용
네거티브를 사용하려면 NOT
을 사용할 수 있습니다. 예 :
SELECT * FROM stack WHERE id NOT BETWEEN 2 and 5;
결과
+----+-----------+
| id | username |
+----+-----------+
| 1 | admin |
| 6 | java |
+----+-----------+
2 rows in set (0.00 sec)
노트
사용법
>
및<
및 not>=
및<=
즉,WHERE id NOT BETWEEN 2 and 5
가WHERE (id < 2 OR id > 5)
와 동일WHERE id NOT BETWEEN 2 and 5
.
BETWEEN
검색에서 사용하는 컬럼에 인덱스가 있다면, MySQL은 해당 인덱스를 범위 스캔에 사용할 수 있습니다.
날짜 범위가있는 SELECT
SELECT ... WHERE dt >= '2017-02-01'
AND dt < '2017-02-01' + INTERVAL 1 MONTH
물론 이것은 BETWEEN
과 23:59:59
포함으로 수행 할 수 있습니다. 그러나 패턴에는 다음과 같은 이점이 있습니다.
- 종료일을 미리 계산하지 않아도됩니다 (시작부터 정확한 길이가되는 경우가 많습니다)
-
BETWEEN
처럼 양쪽 끝점을 포함하지 않으며 '23 : 59 : 59'를 입력하지 마십시오. -
DATE
,TIMESTAMP
,DATETIME
및 마이크로 초 포함DATETIME(6)
합니다. - 윤년, 연말 등을 처리합니다.
- 인덱스 친화적입니다 (따라서
BETWEEN
).