Concepten en syntaxis van joins begrijpen

Voltooid

De meest fundamentele en algemene methode voor het combineren van gegevens uit meerdere tabellen is het gebruik van een JOIN-bewerking. Sommige mensen beschouwen JOIN als een afzonderlijke component in een SELECT-instructie, maar anderen denken er aan als onderdeel van de FROM-component. Deze module beschouwt deze voornamelijk als onderdeel van de FROM-component. In deze module ontdekt u hoe met de FROM-component in een T-SQL SELECT-instructie tussenliggende virtuele tabellen worden gemaakt die in latere fasen van de query worden gebruikt.

De FROM-component en virtuele tabellen

Als u hebt geleerd over de logische volgorde van bewerkingen die worden uitgevoerd wanneer SQL Server een query verwerkt, hebt u gezien dat de FROM-component van een SELECT-instructie de eerste component is die moet worden verwerkt. Met deze component wordt bepaald welke tabel of tabellen de bron van rijen voor de query zijn. De FROM kan verwijzen naar één tabel of meerdere tabellen samenvoegen als gegevensbron voor uw query. U kunt de FROM-component beschouwen als het maken en vullen van een virtuele tabel. Deze virtuele tabel bevat de uitvoer van de FROM-component en wordt gebruikt door componenten van de SELECT-instructie die later worden toegepast, zoals de WHERE-component. Wanneer u extra functionaliteit toevoegt, zoals joinoperators, aan een FROM-component, is het handig om te denken aan het doel van de COMPONENT-elementen van FROM als u rijen wilt toevoegen aan of rijen uit de virtuele tabel wilt verwijderen.

De virtuele tabel die door een FROM-component is gemaakt, is alleen een logische entiteit. In SQL Server wordt geen fysieke tabel gemaakt, of dit nu permanent of tijdelijk is, om de resultaten van de FROM-component op te nemen, omdat deze wordt doorgegeven aan de WHERE-component of andere onderdelen van de query.

De virtuele tabel die door de FROM-component is gemaakt, bevat gegevens uit alle gekoppelde tabellen. Het kan handig zijn om de resultaten te beschouwen als sets en de joinresultaten te conceptualiseren als een Venn-diagram.

A Venn diagram showing the set of an Employee table joined to a SalesOrder table

In de loop van de geschiedenis is de T-SQL-taal uitgebreid met wijzigingen in de ANSI-standaarden (American National Standards Institute) voor de SQL-taal. Een van de meest opvallende plaatsen waar deze wijzigingen zichtbaar zijn, is in de syntaxis voor joins in een FROM-component. In de ANSI SQL-89-standaard zijn joins opgegeven door meerdere tabellen op te nemen in de FROM-component in een door komma's gescheiden lijst. Filters om te bepalen welke rijen moeten worden opgenomen in de WHERE-component, zoals deze:

SELECT p.ProductID, m.Name AS Model, p.Name AS Product
FROM SalesLT.Product AS p, SalesLT.ProductModel AS m
WHERE p.ProductModelID = m.ProductModelID;

Deze syntaxis wordt nog steeds ondersteund door SQL Server, maar vanwege de complexiteit van het weergeven van de filters voor complexe joins, wordt dit niet aanbevolen. Als een WHERE-component per ongeluk wordt weggelaten, kunnen ANSI SQL-89-joins eenvoudig cartesische producten worden en een overmatig aantal resultaatrijen retourneren, prestatieproblemen en mogelijk onjuiste resultaten opleveren.

Als u meer wilt weten over het schrijven van query's met meerdere tabellen in T-SQL, is het belangrijk om het concept van Cartesische producten te begrijpen. In de wiskunde is een Cartesisch product het product van twee sets. Het product van een set van twee elementen en een set van zes elementen is een set van 12 elementen, of 6 x 2. Elk element in de ene set wordt gecombineerd met elk element in de andere set. In het onderstaande voorbeeld hebben we een set namen met twee elementen en een set producten met drie elementen. Het Cartesische product combineert elke naam met elk product dat zes elementen oplevert.

Cartesian product

In databases is een Cartesisch product het resultaat van het combineren van elke rij in de ene tabel tot elke rij van een andere tabel. Het product van een tabel met 10 rijen en een tabel met 100 rijen is een resultatenset met 1000 rijen. Het onderliggende resultaat van een JOIN-bewerking is een Cartesisch product, maar voor de meeste T-SQL-query's is een Cartesisch product niet het gewenste resultaat. In T-SQL treedt een Cartesisch product op wanneer twee invoertabellen worden samengevoegd zonder rekening te houden met relaties tussen deze tabellen. Zonder informatie over relaties retourneert de SQL Server-queryprocessor alle mogelijke combinaties van rijen. Hoewel dit resultaat enkele praktische toepassingen kan hebben, zoals het genereren van testgegevens, is het meestal niet nuttig en kan dit ernstige gevolgen hebben voor de prestaties.

Met de komst van de ANSI SQL-92-standaard is ondersteuning toegevoegd voor de sleutelwoorden JOIN- en ON-componenten. T-SQL biedt ook ondersteuning voor deze syntaxis. Joins worden weergegeven in de FROM-component met behulp van de juiste JOIN-operator. De logische relatie tussen de tabellen, die een filterpredicaat wordt, wordt opgegeven in de ON-component.

In het volgende voorbeeld wordt de vorige query opnieuw uitgevoerd met de nieuwere syntaxis:

SELECT p.ProductID, m.Name AS Model, p.Name AS Product
FROM SalesLT.Product AS p
JOIN SalesLT.ProductModel AS m
    ON p.ProductModelID = m.ProductModelID;

Notitie

De ANSI SQL-92-syntaxis maakt het moeilijker om onbedoelde Cartesische producten te maken. Zodra het trefwoord JOIN is toegevoegd, wordt er een syntaxisfout gegenereerd als er een ON-component ontbreekt, tenzij de JOIN is opgegeven als CROSS JOIN.