Sök…
Introduktion
SELECT-uttalandet är kärnan i de flesta SQL-frågor. Den definierar vilken resultatuppsättning som ska returneras av frågan och används nästan alltid i samband med FROM-klausulen, som definierar vilken del av databasen som ska frågas.
Syntax
VÄLJ [DISTINCT] [kolumn1] [, [kolumn2] ...]
FRÅN [tabell]
[VAR villkor]
[GRUPP AV [kolumn1] [, [kolumn2] ...][HAR [kolumn1] [, [kolumn2] ...]
[BESTÄLLNING AV ASC | DESC]
Anmärkningar
SELECT bestämmer vilka kolumners data som ska returneras och i vilken ordning FRÅN en given tabell (med tanke på att de matchar de andra kraven i din fråga specifikt - var och med filter och sammanfogningar).
SELECT Name, SerialNumber
FROM ArmyInfo
returnerar bara resultat från kolumnerna Name
och Serial Number
, men inte från kolumnen som heter Rank
, till exempel
SELECT *
FROM ArmyInfo
indikerar att alla kolumner kommer att returneras. Observera dock att det är dåligt att SELECT *
eftersom du bokstavligen returnerar alla kolumner i en tabell.
Använd jokertecken för att välja alla kolumner i en fråga.
Överväg en databas med följande två tabeller.
Medarbetarnas tabell:
Id | fNAME | LNAME | DeptId |
---|---|---|---|
1 | James | Smed | 3 |
2 | John | Johnson | 4 |
Avdelningstabell:
Id | namn |
---|---|
1 | försäljning |
2 | marknadsföring |
3 | Finansiera |
4 | DEN |
Enkel markering
*
är det jokertecken som används för att välja alla tillgängliga kolumner i en tabell.
När det används som ersättning för explicita kolumnnamn, returnerar det alla kolumner i alla tabeller som en fråga väljer FROM
. Denna effekt gäller alla tabeller som frågan har åtkomst via sina JOIN
klausuler.
Tänk på följande fråga:
SELECT * FROM Employees
Det returnerar alla fält i alla rader i tabellen Employees
:
Id | fNAME | LNAME | DeptId |
---|---|---|---|
1 | James | Smed | 3 |
2 | John | Johnson | 4 |
Punktnotation
För att välja alla värden från en specifik tabell kan jokerteckenet tillämpas på tabellen med punktnotation .
Tänk på följande fråga:
SELECT
Employees.*,
Departments.Name
FROM
Employees
JOIN
Departments
ON Departments.Id = Employees.DeptId
Detta kommer att returnera en datauppsättning med alla fält i Employee
följt av bara fältet Name
i tabellen Departments
:
Id | fNAME | LNAME | DeptId | namn |
---|---|---|---|---|
1 | James | Smed | 3 | Finansiera |
2 | John | Johnson | 4 | DEN |
Varningar mot användning
Det rekommenderas generellt att användning av *
undviks i produktionskod där det är möjligt, eftersom det kan orsaka ett antal potentiella problem inklusive:
- Överskott av IO, nätverksbelastning, minnesanvändning och så vidare på grund av att databasmotorn läser data som inte behövs och skickar den till frontkoden. Detta är särskilt ett problem där det kan finnas stora fält som de som används för att lagra långa anteckningar eller bifogade filer.
- Ytterligare överskott av IO om databasen behöver spola interna resultat till disken som en del av behandlingen för en fråga som är mer komplex än
SELECT <columns> FROM <table>
. - Extra bearbetning (och / eller ännu mer IO) om några av de onödiga kolumnerna är:
- beräknade kolumner i databaser som stöder dem
- i fallet att välja från en vy kolumner från en tabell / vy som frågeaptimeraren annars skulle kunna optimera
- Potentialen för oväntade fel om kolumner läggs till i tabeller och vyer senare som resulterar i tvetydiga kolumnnamn. Till exempel
SELECT * FROM orders JOIN people ON people.id = orders.personid ORDER BY displayname
- om endisplayname
heterdisplayname
läggs till i ordertabellen så att användare kan ge sina beställningar meningsfulla namn för framtida referens kommer kolumnnamnet att visas två gånger i utgången så attORDER BY
klausulen kommer att vara tvetydig vilket kan orsaka fel ("tvetydigt kolumnnamn" i de senaste MS SQL Server-versionerna), och om inte i detta exempel kan din applikationskod börja visa ordningsnamnet där personens namn är avsedd för att den nya kolumnen är den första av det namn som returneras, och så vidare.
När kan du använda *
, med ovanstående varning i åtanke?
Även om det bäst undviks i produktionskod är det bra att använda *
som en kortfattning när man utför manuella frågor mot databasen för undersökning eller prototyparbete.
Ibland gör designbeslut i din ansökan det oundvikligt (i sådana fall föredrar du tablealias.*
bara *
där det är möjligt).
När EXISTS
använder EXISTS
, som SELECT A.col1, A.Col2 FROM A WHERE EXISTS (SELECT * FROM B where A.ID = B.A_ID)
, SELECT A.col1, A.Col2 FROM A WHERE EXISTS (SELECT * FROM B where A.ID = B.A_ID)
vi inga data från B. Därför är en koppling onödig, och motorn vet att inga värden från B ska returneras, vilket innebär att ingen prestanda träffas för att använda *
. På COUNT(*)
sätt är COUNT(*)
bra eftersom det inte heller returnerar någon av kolumnerna, så det behöver bara läsas och bearbetas de som används för filtreringsändamål.
Välja med villkor
Den grundläggande syntaxen för SELECT med WHERE-klausulen är:
SELECT column1, column2, columnN
FROM table_name
WHERE [condition]
[Villkoret] kan vara vilket som helst SQL-uttryck, specificerat med jämförelse eller logiska operatörer som>, <, =, <>,> =, <=, LIKE, NOT, IN, MELLAN etc.
Följande uttalande returnerar alla kolumner från tabellen "Bilar" där statuskolumnen är "KLAR":
SELECT * FROM Cars WHERE status = 'READY'
Se VAR och HAR för fler exempel.
Välj enskilda kolumner
SELECT
PhoneNumber,
Email,
PreferredContact
FROM Customers
Detta uttalande returnerar kolumnerna PhoneNumber
, Email
och PreferredContact
från alla rader i Customers
. Kolumnerna kommer också att returneras i den sekvens som de visas i SELECT
klausulen.
Resultatet blir:
Telefonnummer | E-post | PreferredContact |
---|---|---|
3347927472 | [email protected] | TELEFON |
2137921892 | [email protected] | E-POST |
NULL | [email protected] | E-POST |
Om flera tabeller sammanfogas kan du välja kolumner från specifika tabeller genom att ange tabellnamnet före [table_name].[column_name]
: [table_name].[column_name]
SELECT
Customers.PhoneNumber,
Customers.Email,
Customers.PreferredContact,
Orders.Id AS OrderId
FROM
Customers
LEFT JOIN
Orders ON Orders.CustomerId = Customers.Id
* AS OrderId
betyder att Id
fältet i Orders
kommer att returneras som en kolumn med namnet OrderId
. Se val med kolumnalias för ytterligare information.
För att undvika att använda långa tabellnamn kan du använda tabellalias. Detta minskar smärtan att skriva långa tabellnamn för varje fält som du väljer i skenorna. Om du utför en självanslutning (en sammanfogning mellan två instanser av samma tabell) måste du använda tabellalias för att skilja dina tabeller. Vi kan skriva ett tabellalias som Customers c
eller Customers AS c
. Här fungerar c
som ett alias för Customers
och vi kan välja låt oss säga Email
så här: c.Email
.
SELECT
c.PhoneNumber,
c.Email,
c.PreferredContact,
o.Id AS OrderId
FROM
Customers c
LEFT JOIN
Orders o ON o.CustomerId = c.Id
VÄLJ Använd kolumnalias
Kolumnalias används främst för att förkorta koden och göra kolumnnamnen mer läsbara.
Koden blir kortare eftersom långa tabellnamn och onödig identifiering av kolumner (t.ex. kan det finnas två ID: er i tabellen, men endast en används i uttalandet) kan undvikas. Tillsammans med tabellalias kan du använda längre beskrivande namn i databasstrukturen medan du håller frågor om den strukturen kortfattade.
Dessutom krävs de ibland, till exempel i vyer, för att namnge beräknade utgångar.
Alla versioner av SQL
Aliaser kan skapas i alla versioner av SQL med hjälp av dubbla citat ( "
).
SELECT
FName AS "First Name",
MName AS "Middle Name",
LName AS "Last Name"
FROM Employees
Olika versioner av SQL
Du kan använda enstaka citat ( '
), dubbla citat ( "
) och fyrkantiga parenteser ( []
) för att skapa ett alias i Microsoft SQL Server.
SELECT
FName AS "First Name",
MName AS 'Middle Name',
LName AS [Last Name]
FROM Employees
Båda kommer att resultera i:
Förnamn | Mellannamn | Efternamn |
---|---|---|
James | John | Smed |
John | James | Johnson |
Michael | Marcus | Williams |
Detta uttalande kommer att returnera FName
och LName
kolumner med ett givet namn (ett alias). Detta uppnås med hjälp av AS
operatören följt av aliaset, eller genom att bara skriva alias direkt efter kolumnnamnet. Detta betyder att följande fråga har samma resultat som ovan.
SELECT
FName "First Name",
MName "Middle Name",
LName "Last Name"
FROM Employees
Förnamn | Mellannamn | Efternamn |
---|---|---|
James | John | Smed |
John | James | Johnson |
Michael | Marcus | Williams |
Den uttryckliga versionen (dvs att använda AS
operatören) är dock mer läsbar.
Om aliaset har ett enda ord som inte är ett reserverat ord, kan vi skriva det utan enstaka citat, dubbla citat eller parenteser:
SELECT
FName AS FirstName,
LName AS LastName
FROM Employees
Förnamn | Efternamn |
---|---|
James | Smed |
John | Johnson |
Michael | Williams |
Ytterligare en tillgänglig variation i MS SQL Server är <alias> = <column-or-calculation>
, till exempel:
SELECT FullName = FirstName + ' ' + LastName,
Addr1 = FullStreetAddress,
Addr2 = TownName
FROM CustomerDetails
vilket motsvarar:
SELECT FirstName + ' ' + LastName As FullName
FullStreetAddress As Addr1,
TownName As Addr2
FROM CustomerDetails
Båda kommer att resultera i:
Fullständiga namn | Addr1 | Addr2 |
---|---|---|
James Smith | 123 AnyStreet | Townville |
John Johnson | 668 MyRoad | Anytown |
Michael Williams | 999 High End Dr | Williamsburgh |
Vissa tycker att använda =
istället för As
lättare att läsa, även om många rekommenderar mot detta format, främst för att det inte är standard så att det inte stöds av alla databaser. Det kan orsaka förvirring med andra användningar av =
-tecknet.
Alla versioner av SQL
Om du behöver använda reserverade ord kan du också använda parenteser eller citat för att fly:
SELECT
FName as "SELECT",
MName as "FROM",
LName as "WHERE"
FROM Employees
Olika versioner av SQL
På samma sätt kan du undgå nyckelord i MSSQL med alla olika tillvägagångssätt:
SELECT
FName AS "SELECT",
MName AS 'FROM',
LName AS [WHERE]
FROM Employees
VÄLJ | FRÅN | VAR |
---|---|---|
James | John | Smed |
John | James | Johnson |
Michael | Marcus | Williams |
Dessutom kan ett kolumnalias användas vilken som helst av de sista klausulerna för samma fråga, t.ex. en ORDER BY
:
SELECT
FName AS FirstName,
LName AS LastName
FROM
Employees
ORDER BY
LastName DESC
Du får dock inte använda
SELECT
FName AS SELECT,
LName AS FROM
FROM
Employees
ORDER BY
LastName DESC
För att skapa ett alias från dessa reserverade ord ( SELECT
och FROM
).
Detta kommer att orsaka många fel vid körning.
Urval med sorterade resultat
SELECT * FROM Employees ORDER BY LName
Detta uttalande returnerar alla kolumner från tabellen Employees
.
Id | fNAME | LNAME | Telefonnummer |
---|---|---|---|
2 | John | Johnson | 2468101214 |
1 | James | Smed | 1234567890 |
3 | Michael | Williams | 1357911131 |
SELECT * FROM Employees ORDER BY LName DESC
Eller
SELECT * FROM Employees ORDER BY LName ASC
Detta uttalande ändrar sorteringsriktningen.
Man kan också ange flera sorteringskolumner. Till exempel:
SELECT * FROM Employees ORDER BY LName ASC, FName ASC
Detta exempel kommer att sortera resultaten först efter LName
och sedan, för poster som har samma LName
, sortera efter FName
. Detta ger dig ett resultat som liknar det du skulle hitta i en telefonbok.
För att spara ny typ av kolumnnamn i ORDER BY
klausulen är det möjligt att istället använda kolumnens nummer. Observera att kolumnnummer börjar från 1.
SELECT Id, FName, LName, PhoneNumber FROM Employees ORDER BY 3
Du kan också bädda in ett CASE
uttalande i ORDER BY
klausulen.
SELECT Id, FName, LName, PhoneNumber FROM Employees ORDER BY CASE WHEN LName='Jones` THEN 0 ELSE 1 END ASC
Detta kommer att sortera dina resultat så att alla poster med LName
på "Jones" överst.
Välj kolumner som har namn efter reserverade nyckelord
När ett kolumnnamn matchar ett reserverat nyckelord kräver standard SQL att du bifogar det i dubbla citattecken:
SELECT
"ORDER",
ID
FROM ORDERS
Observera att det gör kolumnnamnet skiftlägeskänsligt.
Vissa DBMS-enheter har egna sätt att citera namn. Till exempel använder SQL Server fyrkantiga parenteser för detta ändamål:
SELECT
[Order],
ID
FROM ORDERS
medan MySQL (och MariaDB) som standard använder backticks:
SELECT
`Order`,
id
FROM orders
Val av angivet antal poster
SQL 2008-standarden definierar FETCH FIRST
klausulen för att begränsa antalet returnerade poster.
SELECT Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
FETCH FIRST 10 ROWS ONLY
Denna standard stöds endast i nyare versioner av vissa RDMS: er. Leverantörsspecifik icke-standardsyntax finns i andra system. Progress OpenEdge 11.x stöder också FETCH FIRST <n> ROWS ONLY
syntax.
Dessutom OFFSET <m> ROWS
innan FETCH FIRST <n> ROWS ONLY
över rader innan du hämtar rader.
SELECT Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
OFFSET 5 ROWS
FETCH FIRST 10 ROWS ONLY
Följande fråga stöds i SQL Server och MS Access:
SELECT TOP 10 Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
För att göra samma sak i MySQL eller PostgreSQL måste LIMIT
sökordet användas:
SELECT Id, ProductName, UnitPrice, Package
FROM Product
ORDER BY UnitPrice DESC
LIMIT 10
I Oracle kan samma göras med ROWNUM
:
SELECT Id, ProductName, UnitPrice, Package
FROM Product
WHERE ROWNUM <= 10
ORDER BY UnitPrice DESC
Resultat : 10 poster.
Id ProductName UnitPrice Package
38 Côte de Blaye 263.50 12 - 75 cl bottles
29 Thüringer Rostbratwurst 123.79 50 bags x 30 sausgs.
9 Mishi Kobe Niku 97.00 18 - 500 g pkgs.
20 Sir Rodney's Marmalade 81.00 30 gift boxes
18 Carnarvon Tigers 62.50 16 kg pkg.
59 Raclette Courdavault 55.00 5 kg pkg.
51 Manjimup Dried Apples 53.00 50 - 300 g pkgs.
62 Tarte au sucre 49.30 48 pies
43 Ipoh Coffee 46.00 16 - 500 g tins
28 Rössle Sauerkraut 45.60 25 - 825 g cans
Säljare Nuances:
Det är viktigt att notera att TOP
i Microsoft SQL fungerar efter WHERE
klausulen och kommer att returnera det angivna antalet resultat om de finns någonstans i tabellen, medan ROWNUM
fungerar som en del av WHERE
klausulen så om andra villkor inte finns i angivet antal rader i början av tabellen, får du noll resultat när det kan finnas andra att hitta.
Välja med tabellalias
SELECT e.Fname, e.LName
FROM Employees e
Medarbetartabellen ges aliaset 'e' direkt efter tabellnamnet. Detta hjälper till att ta bort tvetydighet i scenarier där flera tabeller har samma fältnamn och du måste vara specifik för vilken tabell du vill returnera data från.
SELECT e.Fname, e.LName, m.Fname AS ManagerFirstName
FROM Employees e
JOIN Managers m ON e.ManagerId = m.Id
Observera att när du definierar ett alias kan du inte använda det kanoniska tabellnamnet längre. dvs.
SELECT e.Fname, Employees.LName, m.Fname AS ManagerFirstName
FROM Employees e
JOIN Managers m ON e.ManagerId = m.Id
skulle kasta ett fel.
Det är värt att notera tabellalias - mer formellt "intervallvariabler" - infördes i SQL-språket för att lösa problemet med duplikatkolumner orsakade av INNER JOIN
. SQL-standarden 1992 korrigerade denna tidigare designfel genom att introducera NATURAL JOIN
(implementerad i mySQL, PostgreSQL och Oracle men ännu inte i SQL Server), vars resultat aldrig har duplicerade kolumnnamn. Exemplet ovan är intressant genom att tabellerna sammanfogas i kolumner med olika namn ( Id
och ManagerId
) men inte ska förenas i kolumnerna med samma namn ( LName
, FName
), vilket kräver att namnet på kolumnerna ska utföras före anslutningen:
SELECT Fname, LName, ManagerFirstName
FROM Employees
NATURAL JOIN
( SELECT Id AS ManagerId, Fname AS ManagerFirstName
FROM Managers ) m;
Observera att även om en alias / intervallvariabel måste deklareras för den dervierade tabellen (annars kommer SQL att kasta ett fel), är det aldrig vettigt att använda den faktiskt i frågan.
Välj rader från flera tabeller
SELECT *
FROM
table1,
table2
SELECT
table1.column1,
table1.column2,
table2.column1
FROM
table1,
table2
Detta kallas tvärprodukt i SQL, det är samma som tvärprodukt i uppsättningar
Dessa uttalanden returnerar de valda kolumnerna från flera tabeller i en fråga.
Det finns inget specifikt samband mellan kolumnerna som returneras från varje tabell.
Välja med aggregerade funktioner
Medel
AggregatfunktionenAVG()
returnerar genomsnittet av de valda värdena. SELECT AVG(Salary) FROM Employees
Samlade funktioner kan också kombineras med var-klausulen. SELECT AVG(Salary) FROM Employees where DepartmentId = 1
Samlade funktioner kan också kombineras med grupp efter klausul. Om anställd kategoriseras med flera avdelningar och vi vill hitta genomsnittslön för varje avdelning kan vi använda följande fråga.
SELECT AVG(Salary) FROM Employees GROUP BY DepartmentId
Minimum
MIN()
returnerar minimivärden för valda värden. SELECT MIN(Salary) FROM Employees
Maximal
Den sammanlagdaMAX()
-funktionen kommer att returnera det maximala valda värdet. SELECT MAX(Salary) FROM Employees
Räkna
Den samlade funktionenCOUNT()
returnerar antalet valda värden. SELECT Count(*) FROM Employees
Det kan också kombineras med förutsättningar för att få räknat antal rader som uppfyller specifika villkor. SELECT Count(*) FROM Employees where ManagerId IS NOT NULL
Specifika kolumner kan också anges för att få antalet värden i kolumnen. Observera att NULL
värden inte räknas. Select Count(ManagerId) from Employees
Räkna kan också kombineras med det distinkta nyckelordet för ett tydligt antal. Select Count(DISTINCT DepartmentId) from Employees
Summa
Den sammanlagda funktionenSUM()
returnerar summan av de valda värdena för alla rader. SELECT SUM(Salary) FROM Employees
Välja med noll
SELECT Name FROM Customers WHERE PhoneNumber IS NULL
Val med nollar tar en annan syntax. Använd inte =
, använd IS NULL
eller är IS NOT NULL
istället.
Välj med CASE
När resultaten måste ha en viss logik "på väg" kan man använda CASE-uttalandet för att implementera det.
SELECT CASE WHEN Col1 < 50 THEN 'under' ELSE 'over' END threshold
FROM TableName
också kan kedjas
SELECT
CASE WHEN Col1 < 50 THEN 'under'
WHEN Col1 > 50 AND Col1 <100 THEN 'between'
ELSE 'over'
END threshold
FROM TableName
Man kan också ha CASE
inuti en annan CASE
uttalande
SELECT
CASE WHEN Col1 < 50 THEN 'under'
ELSE
CASE WHEN Col1 > 50 AND Col1 <100 THEN Col1
ELSE 'over' END
END threshold
FROM TableName
Välj utan att låsa bordet
Ibland när tabeller oftast (eller bara) används för läsning, hjälper inte indexering längre och varje lilla räknas, kan man använda markeringar utan LOCK för att förbättra prestandan.
SQL Server
SELECT * FROM TableName WITH (nolock)
MySQL
SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM TableName;
SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Orakel
SET TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
SELECT * FROM TableName;
DB2
SELECT * FROM TableName WITH UR;
där UR
står för "otillåtna läsning".
Om det används i tabellen med rekordändringar pågår kan det ha oförutsägbara resultat.
Välj distinkt (endast unika värden)
SELECT DISTINCT ContinentCode
FROM Countries;
Denna fråga returnerar alla DISTINCT
(unika, olika) värden från kolumnen ContinentCode
från tabellen Countries
ContinentCode |
---|
OC |
EU |
SOM |
NA |
AF |
Välj med villkor för flera värden från kolumnen
SELECT * FROM Cars WHERE status IN ( 'Waiting', 'Working' )
Detta motsvarar semantiskt
SELECT * FROM Cars WHERE ( status = 'Waiting' OR status = 'Working' )
dvs value IN ( <value list> )
är en kortfattad för disjunktion (logisk OR
).
Få aggregerat resultat för radgrupper
Räkna rader baserade på ett specifikt kolumnvärde:
SELECT category, COUNT(*) AS item_count
FROM item
GROUP BY category;
Få medelinkomst per avdelning:
SELECT department, AVG(income)
FROM employees
GROUP BY department;
Det viktiga är att endast välja kolumner som anges i GROUP BY
klausulen eller som används med sammanlagda funktioner .
Där WHERE
klausulen kan också användas med GROUP BY
, men WHERE
filtrerar bort poster innan någon gruppering görs:
SELECT department, AVG(income)
FROM employees
WHERE department <> 'ACCOUNTING'
GROUP BY department;
Om du behöver filtrera resultaten efter gruppering, t.ex. för att bara se avdelningar vars genomsnittliga inkomst är större än 1000, måste du använda HAVING
klausulen:
SELECT department, AVG(income)
FROM employees
WHERE department <> 'ACCOUNTING'
GROUP BY department
HAVING avg(income) > 1000;
Välj med mer än 1 villkor.
AND
nyckelordet används för att lägga till fler villkor i frågan.
namn | Ålder | Kön |
---|---|---|
Sam | 18 | M |
John | 21 | M |
Guppa | 22 | M |
Mary | 23 | F |
SELECT name FROM persons WHERE gender = 'M' AND age > 20;
Detta kommer att returnera:
namn |
---|
John |
Guppa |
med OR
nyckelord
SELECT name FROM persons WHERE gender = 'M' OR age < 20;
Detta kommer att återvända:
namn |
---|
Sam |
John |
Guppa |
Dessa sökord kan kombineras för att möjliggöra mer komplexa kriterier kombinationer:
SELECT name
FROM persons
WHERE (gender = 'M' AND age < 20)
OR (gender = 'F' AND age > 20);
Detta kommer att återvända:
namn |
---|
Sam |
Mary |