Granska SELECT-instruktionen

Slutförd

Transact-SQL eller T-SQL är en dialekt av DET ANSI-standardspråk för SQL som används av Microsoft SQL-produkter och -tjänster. Det liknar standard-SQL. Det mesta av vårt fokus kommer att ligga på SELECT-instruktionen, som har överlägset flest alternativ och varianter av en DML-instruktion.

Vi börjar med att titta på hur en SELECT-instruktion bearbetas på hög nivå. Ordningen i vilken en SELECT-instruktion skrivs är inte den ordning i vilken den utvärderas och bearbetas av SQL Server-databasmotorn.

Överväg följande fråga:

SELECT OrderDate, COUNT(OrderID) AS Orders
FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate
HAVING COUNT(OrderID) > 1
ORDER BY OrderDate DESC;

Frågan består av en SELECT-instruktion som består av flera satser, som var och en definierar en specifik åtgärd som måste tillämpas på de data som hämtas. Innan vi undersöker körningens ordningsföljd för operationer ska vi kort ta en titt på vad den här frågan gör, även om detaljerna för de olika klausulerna inte kommer att omfattas i den här modulen.

SELECT-satsen returnerar kolumnen OrderDate och antalet OrderID-värden, som tilldelas namnet (eller aliaset) Orders:

SELECT OrderDate, COUNT(OrderID) AS Orders

FROM-satsen identifierar vilken tabell som är källan till raderna för frågan. I det här fallet är det tabellen Sales.SalesOrder :

FROM Sales.SalesOrder

WHERE-satsen filtrerar bort rader från resultaten och behåller endast de rader som uppfyller det angivna villkoret. i det här fallet beställningar som har statusen "levererad":

WHERE Status = 'Shipped'

GROUP BY-satsen tar de rader som uppfyllde filtervillkoret och grupperar dem efter OrderDate, så att alla rader med samma OrderDate betraktas som en enda grupp och en rad returneras för varje grupp:

GROUP BY OrderDate

När grupperna har skapats filtrerar HAVING-satsen grupperna baserat på dess egna predikat. Endast datum med mer än en beställning inkluderas i resultatet:

HAVING COUNT(OrderID) > 1

För att förhandsgranska fråga är den sista satsen ORDER BY, som sorterar utdata i fallande ordning av OrderDate:

ORDER BY OrderDate DESC;

Nu när du har sett vad varje sats gör ska vi titta på i vilken ordning SQL Server faktiskt utvärderar dem:

  1. FROM-satsen utvärderas först för att tillhandahålla källraderna för resten av satsen. En virtuell tabell skapas och skickas till nästa steg.
  2. WHERE-satsen ska utvärderas härnäst för att filtrera de rader i källtabellen som matchar ett predikat. Den filtrerade virtuella tabellen skickas till nästa steg.
  3. GROUP BY är nästa steg och ordnar raderna i den virtuella tabellen enligt unika värden som finns i LISTAN GROUP BY. En ny virtuell tabell skapas som innehåller listan över grupper och skickas till nästa steg. Från och med nu i åtgärdsflödet kan endast kolumner i GROUP BY-listan eller aggregerade funktioner refereras till av andra element.
  4. HAVING-satsen utvärderas härnäst och filtrerar bort hela grupper baserat på dess predikat. Den virtuella tabell som skapades i steg 3 filtreras och skickas till nästa steg.
  5. SELECT-satsen körs slutligen och avgör vilka kolumner som ska visas i frågeresultatet. Eftersom SELECT-satsen utvärderas efter de andra stegen kan inga kolumnalias (i vårt exempel Beställningar) som skapats där användas i GROUP BY- eller HAVING-satsen.
  6. ORDER BY-satsen är den sista som ska köras och sorterar raderna enligt kolumnlistan.

Här är den logiska ordningen vid körningen av SELECT-instruktionen ovan för att tillämpa den här förståelsen på vår exempelfråga:

FROM Sales.SalesOrder
WHERE Status = 'Shipped'
GROUP BY OrderDate 
HAVING COUNT(OrderID) > 1
SELECT OrderDate, COUNT(OrderID) AS Orders
ORDER BY OrderDate DESC;

Alla möjliga satser krävs inte i varje SELECT-instruktion som du skriver. Den enda obligatoriska satsen är SELECT-satsen, som i vissa fall kan användas på egen hand. Vanligtvis ingår även en FROM-sats för att identifiera tabellen som efterfrågas. Dessutom har Transact-SQL andra satser som kan läggas till.

Som du har sett skriver du inte T-SQL-frågor i samma ordning som de utvärderas logiskt. Körningsordningen för utvärderingen avgör vilka data som är tillgängliga för vilka satser, eftersom en sats endast har åtkomst till information som redan gjorts tillgänglig från en redan bearbetad sats. Därför är det viktigt att förstå den sanna logiska bearbetningsordningen när du skriver frågor.

Markera alla kolumner

SELECT-satsen kallas ofta SELECT-listan eftersom den visar de värden som ska returneras i frågans resultat.

Den enklaste formen av en SELECT-sats är användningen av asterisktecknet (*) för att returnera alla kolumner. När den används i T-SQL-frågor kallas den för en stjärna. Även om SELECT * är lämpligt för ett snabbtest bör du undvika att använda det i produktionsarbetet av följande skäl:

  • Ändringar i tabellen som lägger till eller ordnar om kolumner återspeglas i frågeresultatet, vilket kan resultera i oväntade utdata för program eller rapporter som använder frågan.
  • Att returnera data som inte behövs kan göra dina frågor långsammare och orsaka prestandaproblem om källtabellen innehåller ett stort antal rader.

I följande exempel hämtas till exempel alla kolumner från tabellen (hypotetisk) Production.Product .

SELECT * FROM Production.Product;

Resultatet från den här frågan är en raduppsättning som innehåller alla kolumner för alla rader i tabellen, som kan se ut ungefär så här:

ProductID

Name

ProduktNummer

Färg

Standardkostnad

Listpris

Storlek

Vikt

ProductCatID

680

HL-ram för vägcykel – svart, 58

FR-R92B-58

Svart

1059.31

1431.5

58

1016.04

18

706

HL Road Frame – röd, 58

FR-R92R-58

Röd

1059.31

1431.5

58

1016.04

18

707

Sport – 100-hjälm, röd

HL-U509-R

Röd

13.0863

34.99

35

708

Sport-100-hjälm, svart

HL-U509

Svart

13.0863

34.99

35

...

...

...

...

...

...

...

...

...

Välja specifika kolumner

Med en explicit kolumnlista kan du ha kontroll över exakt vilka kolumner som returneras och i vilken ordning. Varje kolumn i resultatet har namnet på kolumnen som rubrik.

Tänk till exempel på följande fråga; som återigen använder den hypotetiska tabellen Production.Product .

SELECT ProductID, Name, ListPrice, StandardCost
‎FROM Production.Product;

Den här gången innehåller resultaten endast de angivna kolumnerna:

ProductID

Name

Listpris

Standardkostnad

680

HL-ram för vägcykel – svart, 58

1431.5

1059.31

706

HL Road Frame – röd, 58

1431.5

1059.31

707

Sport – 100-hjälm, röd

34.99

13.0863

708

Sport-100-hjälm, svart

34.99

13.0863

...

...

...

...

Välja uttryck

Förutom att hämta kolumner som lagras i den angivna tabellen kan en SELECT-sats utföra beräkningar och manipuleringar, som använder operatorer för att kombinera kolumner och värden eller flera kolumner. Resultatet av beräkningen eller manipulationen måste vara ett envärdesresultat (skalärt) som visas i resultatet som en separat kolumn.

Följande fråga innehåller till exempel två uttryck:

SELECT ProductID,
      Name + '(' + ProductNumber + ')',
  ListPrice - StandardCost
FROM Production.Product;

Resultatet från den här frågan kan se ut ungefär så här:

ProductID

680

HL Road Frame - Svart, 58 (FR-R92B-58)

372.19

706

HL Road Frame - Röd, 58 (FR-R92R-58)

372.19

707

Sport-100 Hjälm, Röd(HL-U509-R)

21.9037

708

Sport-100 Hjälm, Svart (HL-U509)

21.9037

...

...

...

Det finns några intressanta saker att notera om dessa resultat:

  • Kolumnerna som returneras av de två uttrycken har inga kolumnnamn. Beroende på vilket verktyg du använder för att skicka frågan kan ett kolumnnamn som saknas indikeras av en tom kolumnrubrik, en literal indikator för "inget kolumnnamn" eller ett standardnamn som column1. Vi får se hur du anger ett alias för kolumnnamnet i frågan senare i det här avsnittet.
  • Det första uttrycket använder operatorn + för att sammanfoga strängvärden (teckenbaserade) medan det andra uttrycket använder operatorn - för att subtrahera ett numeriskt värde från ett annat. När +-operatorn används med numeriska värden utför den addition. Det är därför viktigt att förstå datatyperna för de kolumner som du tar med i uttryck. Vi diskuterar datatyper i nästa avsnitt.

Ange kolumnalias

Du kan ange ett alias för varje kolumn som returneras av SELECT-frågan, antingen som ett alternativ till källkolumnnamnet eller för att tilldela ett namn till utdata från ett uttryck.

Här är till exempel samma fråga som tidigare, men med alias angivna för var och en av kolumnerna:

SELECT ProductID AS ID,
      Name + '(' + ProductNumber + ')' AS ProductName,
  ListPrice - StandardCost AS Markup
FROM Production.Product;

Resultatet från den här frågan innehåller de angivna kolumnnamnen:

ID

ProductName

Markup

680

HL Road Frame - Svart, 58 (FR-R92B-58)

372.19

706

HL Road Frame - Röd, 58 (FR-R92R-58)

372.19

707

Sport-100 Hjälm, Röd(HL-U509-R)

21.9037

708

Sport-100 Hjälm, Svart (HL-U509)

21.9037

...

...

...

Anteckning

AS-nyckelordet är valfritt när du anger ett alias, men det är bra att inkludera det för förtydligande.

Formatera frågor

Du kan notera i exemplen i det här avsnittet att du kan vara flexibel när det gäller hur du formaterar frågekoden. Du kan till exempel skriva varje sats (eller hela frågan) på en enda rad eller bryta den över flera rader. I de flesta databassystem är koden skiftlägesokänslig och vissa element i T-SQL-språket är valfria (inklusive AS-nyckelordet som nämnts tidigare och till och med semikolonet i slutet av en sats).

Överväg följande riktlinjer för att göra T-SQL-koden lättläst (och därför enklare att förstå och felsöka!):

  • Ange versaler för T-SQL-nyckelord som SELECT, FROM, AS och så vidare. Versaler för nyckelord är en vanlig konvention som gör det lättare att hitta varje del av ett yttrande i ett komplext uttalande.
  • Starta en ny rad för varje huvudsats i ett påstående.
  • Om SELECT-listan innehåller fler än några kolumner, uttryck eller alias bör du överväga att visa varje kolumn på en egen rad.
  • Dra in rader som innehåller underklisslar eller kolumner för att göra det tydligt vilken kod som tillhör varje huvudsats.