mk-prg-net \ ms-sql \ tsql \queries \joins

Cross Join

Grundidee von relationalen Datenbanken ist die Betrachtung von Datenbanken als Mengen und Operationen, wie sie durch die mathematische Mengenlehre definiert sind.

Gegeben sei z.B. eine Menge von Himmelskörpern (Sonne, Jupiter, Erdmond, Ceres, …) und eine Menge von Gewichtsangaben der Himmelskörper, dargestellt in Vielfachen der Erdmasse (1 [=Erde], 0,0123 [=Erdmond], 332981 [=Sonne], …). Auf diesen beiden Mengen kann das sog. Kreuzprodukt gebildetet werden, indem jedes Element der einen Menge mit jedem Element der anderen Menge kombiniert wird. Hat z.B. die Menge der Himmelskörper n Elemente, und die Menge der Erdmassen m Elemente, dann hat das Ergebnis des Kreuzproduktes m * n Elemente.

  |Himmelskörper| == n, |Erdmassen| == m => |Himmelskörper| x |Erdmassen| == m*n

In der Relationalen Datenbank werden Mengen durch Tabellen dargestellt. Das Kreuzprodukt entsteht durch eine spezielle Select-Anweisung, in deren From- Klausel entweder mehrere Tabellen durch den Komma, oder durch den CROSS JOIN Operator kombiniert werden:

use master
go
drop database u3Joins
go
create database u3Joins
go
use u3Joins
go
create table HK (
        Name varchar(255)
)
insert into HK values('Sonne')
insert into HK values('Mond')
create table EM (
        Masse float
)
insert into EM values(332981)
insert into EM values(1)
insert into EM values(0.0123)
go
-- Natürlicher Join (math.: Kreuzprodukt) 
select Name, Masse
 from HK, EM
-- Alternativ
select Name, Masse
from HK CROSS JOIN EM

Inner Join

Bedingt durch Normalisierung bei der Datenmodellierung verteilen sich die Informationen zu Entities auf viele Tabellen. Um alle Daten eines Entity wieder in einem Stück zu bekommen, ist ein verknüpfen der Tabellen nötig (Inner Join).

Das Prinzip der Verknüpfung aus mengentheoretischer Sicht besteht im bilden des Kreuzproduktes zwischen den durch zwei Tabellen dargestellten Mengen, und dem anschließenden Herausfiltern all jener Tupel, bei denen Schlüssel und Fremdschlüssel übereinstimmen. Folgendes Bild demonstriert das Verfahren. Schlüssel und Fremdschlüssel werden dabei durch die astrologischen Symbole der Himmelskörper ausgedrückt.

inner Join

Folgende Übung erklärt schrittweise den Inner Join.

  create table HK (
		ID int  primary key,
        Name varchar(255)
)
insert into HK values(1, 'Sonne')
insert into HK values(3, 'Mond')
create table EM (
		ID int identity,
		HK_ID int foreign key references HK(ID),
        Masse float
)
insert into EM (HK_ID, Masse) values(1, 332981)
insert into EM (HK_ID, Masse) values(3, 0.0123)
-- Um einen Datensatz für die Erde, zu der es keinen Masterdatensatz in HK gibt,
-- einzufügen, müssen kurzfristig Einschränkungen abgeschaltet werden
alter table EM nocheck constraint all
insert into EM (HK_ID, Masse) values(2, 1)
alter table EM check constraint all
go
-- Inner Join (math.: Einschränkung des Kreuzprodukts durch ein Filterkriterium => Relation) 
select 'inner Join', Name, Masse
from HK inner join EM on HK.ID = EM.HK_ID
-- Alternativ
select 'alternativ mit ,', Name, Masse
from HK, EM
where HK.ID = EM.HK_ID
-- Inner Joins sind Kommutativ
select 'kommutativ!', Name, Masse
from EM inner join HK on HK.ID = EM.HK_ID

Outer Join

Left outer Join
Right outer Join
  -- Outer Joins
-- sind nicht Kommutativ !
select 'left outer', Name, Masse
from HK left outer join EM on HK.ID = EM.HK_ID
select 'right outer', Name, Masse
from HK right outer join EM on HK.ID = EM.HK_ID

Cross Apply

Beim Join einer Tabelle mit einer Tabellenwertfuktion können als Parameter der Tabellenwertfunktion nur Konstanten oder TSQL- Variablen eingesetzt werden. Folgender Join liefert nur die Trabanten der Sonne:


  Select H.Name as [Zentralkörper],
	   T.ZentralkoerperTyp as [Typ],
	   H.Masse_in_kg as Masse, 
	   T.Trabant as Trabant,
	   T.Umlaufdauer_Tage,
	   T.TrabantTyp as [Typ Trabant]
from [dbo].[HimmelskoerperTab] as H Join dbo.Trabanten_von('Sonne') as T on H.ID = T.ZentralID
order by Masse desc, Umlaufdauer_Tage

Mittels des CROSS APPLY Operators kann diese Einschränkung überwunden werden. Parameter können hier an Attribute von Datensätzen gebunden werden, welcher der linke Teil von CROSS APPLY liefert. Folgender CROSS APPLY liefert die Trabanten der Sonne, der Planeten usw.

  
Select H.Name as [Zentralkörper],
	   T.ZentralkoerperTyp as [Typ],
	   H.Masse_in_kg / dbo.Erdmasse() as Masse, 
	   T.Trabant as Trabant,
	   T.Umlaufdauer_Tage,
	   T.TrabantTyp as [Typ Trabant],
	   T.Trabantmasse / dbo.Erdmasse() as Trabantmasse
from [dbo].[HimmelskoerperTab] as H CROSS APPLY dbo.Trabanten_von(H.Name) as T
order by Masse desc, Umlaufdauer_Tage 

Select ... into <Tabellenname>...

Mittels Select Into werden neue Tabellen erstellt.

Select über Datenbankgrenzen

Die From- Klausel einer Select Anweisung kann so formuliert werden, daß auf Tabellen von Datenbanken außerhalb des aktuellen Datenbankkontextes (use DBName) erreichbar sind. Dazu ist der Datenbankname dem Besitzernamen voranzustellen:

  use dms
go
select name from dms2.dbo.dirs  -- Zugreifen auf die Dirs- Tabelle in dms2
go

Select über Servergrenzen

Auch über Servergrenzen hinaus sind Selects möglich. Dazu müssen die fernen Server zuerst als Verbindungsserver definiert werden. Dies geschieht mit der gespeicherten Prozedur sp_addlinkedserver.

exec sp_addlinkedserver 'shuttle\msde2'

Nach dieser Registrierung sind auch Datenbankobjekte aus anderen Servern erreichbar, indem der Servernamen dem Namen des Datenbankobjekts vorangestellt wird:

  use dms
go
select * from [shuttle\msde2].dms.dbo.dirs
go

Select ... UNION

Durch UNION können die Ergebnisse mehrerer Select- Abfragen zu einem Resultset zusammengefasst werden. Dabei müssen alle Teilselects die gleiche Spaltenliste zurückgeben. Beispiel:

  -- UNION
-- Bestimmen aller Dateien, die das Wort 'perl' enthalten. Die Daten sind 
-- auf zwei Serverinstanzen verteilt (local und trAC19\MSDE). Durch Union werden
-- beide Teilergebnisse wieder zusammengeführt
select file_id, pos 
from dms.dbo.words
where word like 'perl'
UNION
select file_id + 100000, pos 
from [trAC19\MSDE2].dms.dbo.words
where word like 'perl'
order by file_id, pos
go