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:

  1. Ö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.
  2. 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> .
  3. 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
  4. 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 en displayname heter displayname 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å att ORDER 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

Aggregatfunktionen AVG() 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 sammanlagda MAX() -funktionen kommer att returnera det maximala valda värdet.
SELECT MAX(Salary) FROM Employees

Räkna

Den samlade funktionen COUNT() 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 funktionen SUM() 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

SQLFiddle Demo

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


Modified text is an extract of the original Stack Overflow Documentation
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow