Subquery’s (SQL Server)

  • 18/02/2018
  • 21 minuten om te lezen
    • W
    • M
    • T
    • M
    • j
    • +3

Is van toepassing op: SQL Server (alle ondersteunde versies) Azure SQL Database Azure SQL Managed Instance Azure Synapse Analytics Parallel Data Warehouse

Een subquery is een query die is genest in een SELECT, INSERT, UPDATE, of DELETE instructie, of in een andere subquery. Een subquery kan overal worden gebruikt waar een uitdrukking is toegestaan. In dit voorbeeld wordt een subquery gebruikt als een kolomexpressie met de naam MaxUnitPrice in een SELECT-instructie.

Subquery Fundamentals

Een subquery is ook wordt een innerlijke query of innerlijke selectie genoemd, terwijl de instructie die een subquery bevat ook een uiterlijke query of uiterlijke selectie wordt genoemd.

Veel Transact-SQL-instructies die subquery’s bevatten, kunnen als joins worden geformuleerd. Andere vragen kunnen alleen worden gesteld met subquery’s. In Transact-SQL is er meestal geen prestatieverschil tussen een instructie die een subquery bevat en een semantisch equivalente versie die dat niet doet. In sommige gevallen waarin het bestaan moet worden gecontroleerd, levert een join echter betere prestaties op. Anders moet de geneste query worden verwerkt voor elk resultaat van de buitenste query om ervoor te zorgen dat duplicaten worden verwijderd. In dergelijke gevallen zou een join-benadering betere resultaten opleveren. Het volgende is een voorbeeld van zowel een subquery SELECT als een join SELECT die dezelfde resultaatset retourneren:

Een subquery genest in de buitenste SELECT-instructie heeft de volgende componenten:

  • Een normale SELECT query inclusief de reguliere selectielijstcomponenten.
  • Een normale FROM -clausule met een of meer tabel- of weergavenamen.
  • Een optionele WHERE clausule.
  • Een optionele GROUP BY clausule.
  • Een optionele HAVING -clausule.

De SELECT-query van een subquery staat altijd tussen haakjes. Het mag geen COMPUTE of FOR BROWSE -clausule bevatten, en mag alleen een ORDER BY -clausule bevatten wanneer een TOP-clausule is ook gespecificeerd.

Een subquery kan worden genest in de WHERE of HAVING -clausule van een buitenste SELECT, INSERT, UPDATE of DELETE statement, of in een andere subquery. Er zijn maximaal 32 nesten mogelijk, hoewel de limiet varieert op basis van het beschikbare geheugen en de complexiteit van andere uitdrukkingen in de query. Afzonderlijke zoekopdrachten ondersteunen mogelijk geen nesting tot 32 niveaus. Een subquery kan overal verschijnen waar een uitdrukking kan worden gebruikt, als deze een enkele waarde retourneert.

Als een tabel alleen in een subquery voorkomt en niet in de buitenste query, kunnen kolommen uit die tabel niet worden opgenomen in de output (de geselecteerde lijst van de buitenste query).

Uitspraken die een subquery bevatten, hebben meestal een van deze formaten:

  • WHERE expressie IN (subquery)
  • WHERE expressie vergelijkingsoperator (subquery)
  • WHERE EXISTS (subquery)

In sommige Transact-SQL-instructies kan de subquery worden geëvalueerd alsof het een onafhankelijke vraag. Conceptueel worden de resultaten van de subquery vervangen door de buitenste query (hoewel dit niet noodzakelijk is hoe SQL Server Transact-SQL-instructies met subquery’s daadwerkelijk verwerkt).

Er zijn drie basistypen subquery’s. Degenen die:

  • werken op lijsten die zijn geïntroduceerd met IN, of die door een vergelijkingsoperator zijn gewijzigd door ANY of ALL.
  • Worden geïntroduceerd met een ongewijzigde vergelijkingsoperator en moeten een enkele waarde retourneren.
  • Zijn existentie-tests geïntroduceerd met EXISTS.

Regels voor subquery’s

Een subquery is onderworpen aan de volgende beperkingen:

  • De selectielijst van een subquery die met een vergelijkingsoperator wordt geïntroduceerd, kan slechts één uitdrukking of kolomnaam bevatten (behalve dat EXISTS en IN werken op SELECT * of een lijst, respectievelijk).
  • Als de WHERE -clausule van een externe zoekopdracht een kolomnaam bevat, moet join-compatibel zijn met de kolom in de selectielijst voor subquery’s.
  • De gegevenstypen ntext, text en image kunnen niet worden gebruikt in de geselecteerde lijst met subquery’s.
  • Omdat ze een enkele waarde moeten retourneren, kunnen subquery’s die zijn geïntroduceerd door een ongewijzigde vergelijkingsoperator (één niet gevolgd door het zoekwoord ANY of ALL) mag GROUP BY en HAVING clausules bevatten.
  • De DISTINCT zoekwoord kan niet worden gebruikt met subquery’s die GROUP BY bevatten.
  • De COMPUTE en INTO -clausules kunnen niet worden gespecificeerd.
  • ORDER BY kunnen alleen worden gespecificeerd als TOP ook is gespecificeerd.
  • Een weergave die is gemaakt door een subquery te gebruiken, kan niet worden bijgewerkt.
  • De selectielijst van een subquery die is geïntroduceerd met EXISTS heeft volgens afspraak een asterisk ( *) in plaats van een enkele kolomnaam. De regels voor een subquery geïntroduceerd met EXISTS zijn dezelfde als die voor een standaard selectielijst, omdat een subquery geïntroduceerd met EXISTS een bestaan creëert test en retourneert TRUE of FALSE, in plaats van data.

Kwalificerende kolomnamen in subquery’s

In het volgende voorbeeld geeft de BusinessEntityID-kolom in de WHERE -clausule van de buitenste query wordt impliciet gekwalificeerd door de tabelnaam in de buitenste query FROM -clausule (Sales.Store). De verwijzing naar CustomerID in de geselecteerde lijst van de subquery wordt gekwalificeerd door de subquery FROM -clausule, dat wil zeggen door de tabel Sales.Customer.

De algemene regel is dat kolomnamen in een instructie impliciet worden gekwalificeerd door de tabel waarnaar wordt verwezen in de FROM -clausule op hetzelfde niveau. Als een kolom niet voorkomt in de tabel waarnaar wordt verwezen in de FROM -clausule van een subquery, wordt deze impliciet gekwalificeerd door de tabel waarnaar wordt verwezen in de FROM clausule van de buitenste query.

Hier is hoe de query eruit ziet met deze impliciete aannames gespecificeerd:

Het is nooit fout om de tabelnaam expliciet te vermelden, en het is altijd mogelijk om impliciete aannames over tabelnamen met expliciete kwalificaties te negeren.

Belangrijk

Als een kolom wordt verwezen in een subquery die komt niet voor in de tabel waarnaar wordt verwezen door de subquery “s FROM -clausule, maar bestaat in een tabel waarnaar wordt verwezen door de buitenste query” s FROM clausule, wordt de query uitgevoerd zonder fout. SQL Server kwalificeert de kolom in de subquery impliciet met de tabelnaam in de buitenste query.

Meerdere nesten

Een subquery kan zelf een of meer subquery’s bevatten. Elk aantal subquery’s kan in een statement worden genest.

De volgende query vindt de namen van medewerkers die ook verkopers zijn.

Hier is de resultatenset.

De binnenste query retourneert de verkooppersoon-ID’s. De vraag op het volgende hogere niveau wordt geëvalueerd met deze verkooppersoon-ID’s en retourneert de contact-ID-nummers van de medewerkers. Ten slotte gebruikt de buitenste vraag de contact-ID’s om de namen van de werknemers te vinden.

U kunt deze vraag ook uitdrukken als een join:

Veel zoekopdrachten kunnen worden geëvalueerd door de subquery één keer uit te voeren en de resulterende waarde of waarden in de WHERE -clausule van de buitenste query te vervangen. In query’s die een gecorreleerde subquery bevatten (ook bekend als een herhalende subquery), is de subquery afhankelijk van de buitenste query voor zijn waarden. Dit betekent dat de subquery herhaaldelijk wordt uitgevoerd, één keer voor elke rij die kan worden geselecteerd door de buitenste query. Deze query haalt één instantie op van de voor- en achternaam van elke werknemer waarvoor de bonus in de tabel SalesPerson 5000 is en waarvoor de werknemersidentificatienummers komen overeen in de tabellen Werknemer en Verkooppersoon.

Hier is de resultatenset.

De vorige subquery in deze instructie kan niet onafhankelijk van de buitenste query worden geëvalueerd. Er is een waarde nodig voor Employee.BusinessEntityID, maar deze waarde verandert naarmate SQL Server verschillende rijen in Employee onderzoekt.
Dat is precies hoe dit query wordt geëvalueerd: SQL Server beschouwt elke rij van de tabel Werknemer voor opname in de resultaten door de waarde in elke rij in de innerlijke query te vervangen. Als SQL Server bijvoorbeeld eerst de rij onderzoekt op Syed Abbas, de variabele Employee.BusinessEntityID krijgt de waarde 285, die door SQL Server wordt vervangen utes in de innerlijke zoekopdracht.

Het resultaat is 0 (Syed Abbas heeft geen bonus ontvangen omdat hij geen verkoper), dus de buitenste zoekopdracht evalueert naar:

Omdat dit niet waar is, wordt de rij voor Syed Abbas is niet meegenomen in de resultaten.

Write a Comment

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *