MySQL
VÄLJ
Sök…
Introduktion
SELECT
används för att hämta rader valda från en eller flera tabeller.
Syntax
VÄLJ DISTINCT [uttryck] FRÅN Tabellnamn [VAR villkor]; /// Enkelt Välj
SELECT DISTINCT (a), b ... är samma som SELECT DISTINCT a, b ...
VÄLJ [ALLA | DISTINKT | DISTINCTROW] [HIGH_PRIORITY] [STRAIGHT_JOIN] [SQL_SMALL_RESULT | SQL_BIG_RESULT] [SQL_BUFFER_RESULT] [SQL_CACHE | SQL_NO_CACHE] [SQL_CALC_FOUND_ROWS] uttryck FRÅN tabeller [VAR villkor] [GRUPP AV uttryck] [HAVING villkor] [ORDER BY uttryck [ASC | DESC]] [LIMIT [offset_value] number_rows | LIMIT number_rows OFFSET offset_value] [PROCEDURE procedure_name] [INTO [OUTFILE 'file_name' options | DUMPFIL 'filnamn' | @ variabel1, @ variabel2, ... @variabelt_n] [FÖR UPPDATERING | LOCK IN SHARE MODE]; /// Full Välj syntax
Anmärkningar
Mer information om MySQL: s SELECT
uttalande finns i MySQL Docs .
VÄLJ efter kolumnnamn
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');
Fråga
SELECT id FROM stack;
Resultat
+------+
| id |
+------+
| 1 |
| 2 |
+------+
VÄLJ alla kolumner (*)
Fråga
SELECT * FROM stack;
Resultat
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | admin | admin |
| 2 | stack | stack |
+------+----------+----------+
2 rows in set (0.00 sec)
Du kan välja alla kolumner från en tabell i en sammanfogning genom att göra:
SELECT stack.* FROM stack JOIN Overflow ON stack.id = Overflow.id;
Bästa praxis Använd inte *
såvida du inte felsöker eller hämtar raden / raderna i associerande matriser, annars kan schematändringar (ADD / DROP / omarrangera kolumner) leda till otäcka applikationsfel. Om du ger en lista över kolumner du behöver i din resultatsats kan MySQLs frågeformulär ofta optimera frågan.
Fördelar:
- När du lägger till / tar bort kolumner behöver du inte göra ändringar där du använde
SELECT *
- Det är kortare att skriva
- Du ser också svaren, så kan
SELECT *
-bruk någonsin vara motiverat?
Nackdelar:
- Du returnerar mer data än du behöver. Säg att du lägger till en VARBINARY-kolumn som innehåller 200 000 per rad. Du behöver bara dessa data på ett ställe för en enda post - med
SELECT *
du hamna tillbaka 2 MB per 10 rader som du inte behöver - Explicit om vilka data som används
- Att ange kolumner innebär att du får ett fel när en kolumn tas bort
- Frågefrocessorn måste göra lite mer arbete - ta reda på vilka kolumner som finns på bordet (tack @vinodadhikary)
- Du kan hitta en kolumn lättare
- Du får alla kolumner i sammanfogningar om du använder VÄLJ *
- Du kan inte använda ordinära referenser på ett säkert sätt (men det är dåligt att använda ordinära referenser för kolumner i sig)
- I komplexa frågor med
TEXT
fält kan frågan bromsas ner med mindre optimal temp-tabellbehandling
VÄLJ med VAR
Fråga
SELECT * FROM stack WHERE username = "admin" AND password = "admin";
Resultat
+------+----------+----------+
| id | username | password |
+------+----------+----------+
| 1 | admin | admin |
+------+----------+----------+
1 row in set (0.00 sec)
Fråga med en kapslad SELECT i WHERE-klausulen
WHERE
klausulen kan innehålla valfritt SELECT
uttalande för att skriva mer komplexa frågor. Detta är en "kapslad" fråga
Fråga
Kapslade frågor används vanligtvis för att returnera enstaka atomvärden från frågor för jämförelser.
SELECT title FROM books WHERE author_id = (SELECT id FROM authors WHERE last_name = 'Bar' AND first_name = 'Foo');
Väljer alla användarnamn utan e-postadress
SELECT * FROM stack WHERE username IN (SELECT username FROM signups WHERE email IS NULL);
Friskrivningsklausul: Överväg att använda joins för prestandaförbättringar när du jämför en hel resultatuppsättning.
VÄLJ med LIKE (%)
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" var som helst:
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 |
+----+-----------+
Börjar med "adm":
SELECT * FROM stack WHERE username LIKE "adm%";
+----+----------+
| id | username |
+----+----------+
| 1 | admin |
| 3 | adm |
| 6 | adm now |
+----+----------+
Avsluts med "adm":
SELECT * FROM stack WHERE username LIKE "%adm";
+----+----------+
| id | username |
+----+----------+
| 3 | adm |
+----+----------+
Precis som %
-tecknet i en LIKE
klausul matchar valfritt antal tecken, _
tecknet bara ett tecken. Till exempel,
SELECT * FROM stack WHERE username LIKE "adm_n";
+----+----------+
| id | username |
+----+----------+
| 1 | admin |
+----+----------+
Prestandeanmärkningar Om det finns ett index på username
, då
-
LIKE 'adm'
utför samma sak som '=' adm ' -
LIKE 'adm%
är ett "intervall", liknandeBETWEEN..AND..
Det kan utnyttja ett index i kolumnen bra. -
LIKE '%adm'
(eller någon variant med ett ledande jokertecken) kan inte använda något index. Därför kommer det att bli långsamt. På bord med många rader är det troligtvis så långsamt att det är värdelöst. -
RLIKE
(REGEXP
) tenderar att vara långsammare änLIKE
, men har fler möjligheter. - Medan MySQL erbjuder
FULLTEXT
indexering på många typer av bord och kolumn, deFULLTEXT
är index inte användas för att uppfylla frågor med hjälpLIKE
.
VÄLJ med Alias (AS)
SQL-alias används för att tillfälligt byta namn på en tabell eller en kolumn. De används vanligtvis för att förbättra läsbarheten.
Fråga
SELECT username AS val FROM stack;
SELECT username val FROM stack;
(Obs: AS
är syntaktiskt valfritt.)
Resultat
+-------+
| val |
+-------+
| admin |
| stack |
+-------+
2 rows in set (0.00 sec)
VÄLJ med en begränsningsklausul
Fråga:
SELECT *
FROM Customers
ORDER BY CustomerID
LIMIT 3;
Resultat:
Kundnummer | Köparens namn | Kontaktnamn | Adress | Stad | Postnummer | Land |
---|---|---|---|---|---|---|
1 | Alfreds Futterkiste | Maria Anders | Obere Str. 57 | Berlin | 12209 | Tyskland |
2 | Ana Trujillo Emparedados y helados | Ana Trujillo | Avda. de la Constitución 2222 | México DF | 05021 | mexico |
3 | Antonio Moreno Taquería | Antonio Moreno | Mataderos 2312 | México DF | 05023 | mexico |
Bästa praxis Använd alltid ORDER BY
när du använder LIMIT
; annars kommer raderna du får vara oförutsägbara.
Fråga:
SELECT *
FROM Customers
ORDER BY CustomerID
LIMIT 2,1;
Förklaring:
När en LIMIT
klausul innehåller två siffror tolkas den som LIMIT offset,count
. Så i detta exempel hoppar frågan över två poster och returnerar en.
Resultat:
Kundnummer | Köparens namn | Kontaktnamn | Adress | Stad | Postnummer | Land |
---|---|---|---|---|---|---|
3 | Antonio Moreno Taquería | Antonio Moreno | Mataderos 2312 | México DF | 05023 | mexico |
Notera:
Värdena i LIMIT
klausuler måste vara konstanter; de kanske inte är kolumnvärden.
VÄLJ med DISTINCT
DISTINCT
klausulen efter SELECT
eliminerar duplicerade rader från resultatuppsättningen.
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
fungerar över alla kolumner för att leverera resultaten, inte enskilda kolumner. Det senare är ofta en missuppfattning av nya SQL-utvecklare. I korthet är det distinensen på resultatsatsens radnivå som spelar roll, inte distinensen på kolumnivån. För att visualisera detta, titta på "Audi A1" i ovanstående resultatuppsättning.
För senare versioner av MySQL har DISTINCT
konsekvenser för dess användning tillsammans med ORDER BY
. Inställningen för ONLY_FULL_GROUP_BY
kommer in i spelet enligt följande MySQL Manual-sida med titeln MySQL-hantering av GROUP BY .
VÄLJ med LIKE (_)
Ett _
tecken i ett LIKE
klausulmönster matchar ett enda tecken.
Fråga
SELECT username FROM users WHERE users LIKE 'admin_';
Resultat
+----------+
| username |
+----------+
| admin1 |
| admin2 |
| admin- |
| adminA |
+----------+
VÄLJ med fall eller IF
Fråga
SELECT st.name,
st.percentage,
CASE WHEN st.percentage >= 35 THEN 'Pass' ELSE 'Fail' END AS `Remark`
FROM student AS st ;
Resultat
+--------------------------------+
| name | percentage | Remark |
+--------------------------------+
| Isha | 67 | Pass |
| Rucha | 28 | Fail |
| Het | 35 | Pass |
| Ansh | 92 | Pass |
+--------------------------------+
Eller med IF
SELECT st.name,
st.percentage,
IF(st.percentage >= 35, 'Pass', 'Fail') AS `Remark`
FROM student AS st ;
NB
IF(st.percentage >= 35, 'Pass', 'Fail')
Detta betyder: IF st.percentage> = 35 är SANT och sedan returnera
'Pass'
ELSE return'Fail'
VÄLJ med MELLAN
Du kan använda MELLAN-klausulen för att ersätta en kombination av "större än lika OCH mindre än lika" villkor.
Data
+----+-----------+
| id | username |
+----+-----------+
| 1 | admin |
| 2 | root |
| 3 | toor |
| 4 | mysql |
| 5 | thanks |
| 6 | java |
+----+-----------+
Fråga med operatörer
SELECT * FROM stack WHERE id >= 2 and id <= 5;
Liknande fråga med MELLAN
SELECT * FROM stack WHERE id BETWEEN 2 and 5;
Resultat
+----+-----------+
| id | username |
+----+-----------+
| 2 | root |
| 3 | toor |
| 4 | mysql |
| 5 | thanks |
+----+-----------+
4 rows in set (0.00 sec)
Notera
MELLAN använder
>=
och<=
, inte>
och<
.
Använd INTE MELLAN
Om du vill använda det negativa kan du använda NOT
. Till exempel :
SELECT * FROM stack WHERE id NOT BETWEEN 2 and 5;
Resultat
+----+-----------+
| id | username |
+----+-----------+
| 1 | admin |
| 6 | java |
+----+-----------+
2 rows in set (0.00 sec)
Notera
INTE MELLAN använder
>
och<
och inte>=
och<=
Det vill sägaWHERE id NOT BETWEEN 2 and 5
är samma somWHERE (id < 2 OR id > 5)
.
Om du har ett index i en kolumn som du använder i en BETWEEN
sökning kan MySQL använda det indexet för en avstandsskanning.
VÄLJ med datumintervall
SELECT ... WHERE dt >= '2017-02-01'
AND dt < '2017-02-01' + INTERVAL 1 MONTH
Visst, detta kan göras med BETWEEN
och inkludering av 23:59:59
. Men mönstret har följande fördelar:
- Du har inte förberäknat slutdatumet (som ofta är en exakt längd från början)
- Du inkluderar inte båda slutpunkterna (som
BETWEEN
gör) och skriver inte heller '23: 59: 59 'för att undvika det. - Det fungerar för
DATE
,TIMESTAMP
,DATETIME
och till och med den mikrosekunder som ingårDATETIME(6)
. - Det tar hand om språngdagar, årets slut etc.
- Det är indexvänligt (så är
BETWEEN
).