Einschränkungen beim Left-Join auf einen Datensatz (n:m)

12/01/2010 - 15:53 von Richard Ohl | Report spam
Hallo, ich brauche einen kleinen Denkanschub für T-SQL, bitte. Ich möchte
Daten aus Tabelle A holen und mit Tabelle C verbinden (über Tabelle B n:m
verbunden, oder leer), aber trotzdem nur jeweils _einen_ Datensatz geliefert
bekommen. Bei Abfragen mehrerer Sàtze aus Tabelle A sollen natürlich jeweils
ein Datensatz herauskommen.

Tabelle A
a_id a_daten1
1 foo
2 bar
3 lala

Tabelle C
c_id datetime c_daten1
1 2009-01-01 nada
2 2010-01-01 nix

Tabelle B
a_id c_id
1 1
2 1
1 2

Die Abfrage sollte nun alle Datensàtze von A mit dem aktuellsten aus C
verbinden, Ergebnis:
a_id c_id,
1 2
2 1
3 NULL

Kann ich das in dem (Left) Join statement erledigen? Es sieht schwer machbar
aus, das in einem WHERE zu verpacken, da das ja alle Datensàtze filtern
würde. Grouping mit einem MAX(c.datetime) wird kompliziert, weil ich dann
bei Änderungen ja immer alle Spalten mit gruppieren muss.
Ich habe hier gerade eine Denkblockade...
Vielen Dank für eine Anregung!
Richard
To be stupid, selfish, and have good health are three requirements for
happiness, though if stupidity is lacking, all is lost. -- Gustave Flaubert
 

Lesen sie die antworten

#1 Uwe Ricken
12/01/2010 - 17:20 | Warnen spam
Hallo Richard,

das geht am besten mit einem SubSelect (mal mit Deinen Daten ausprobiert):

USE tempdb
GO

CREATE TABLE dbo.TabelleA
(
a_Id int NOT NULL PRIMARY KEY,
a_daten1 varchar(10) NOT NULL
)
GO

INSERT INTO dbo.TabelleA
(a_Id, a_daten1)
SELECT 1, 'foo'
UNION
SELECT 2, 'bar'
UNION
SELECT 3, 'lala'

CREATE TABLE dbo.TabelleC
(
c_id int NOT NULL PRIMARY KEY,
c_date datetime NOT NULL,
c_daten1 varchar(5) NOT NULL
)

INSERT INTO dbo.TabelleC
(c_id, c_date, c_daten1)
SELECT 1, '20090101', 'nada'
UNION
SELECT 2, '20100101', 'nix'


CREATE TABLE dbo.TabelleB
(
a_id int NOT NULL,
c_id int NOT NULL,

CONSTRAINT pk_TabelleB PRIMARY KEY
(
a_id,
c_id
)
)

INSERT INTO dbo.TabelleB
(a_id, c_id)
SELECT 1, 1
UNION
SELECT 2, 1
UNION
SELECT 1, 2

SELECT * FROM dbo.TabelleA
SELECT * FROM dbo.TabelleB
SELECT * FROM dbo.TabelleC



SELECT a.a_id,
a.a_daten1,
r.MaxDate,
r.MaxDaten
FROM dbo.TabelleA a INNER JOIN
(
SELECT b.a_id,
MAX(c.c_date) AS MaxDate,
MAX(c.c_daten1) AS MaxDaten
FROM dbo.TabelleB b INNER JOIN dbo.TabelleC c
ON (b.c_id = c.c_id)
GROUP BY
b.a_id
) r
ON (a.a_Id = r.a_id)

GO

DROP TABLE dbo.TabelleA
DROP TABLE dbo.TabelleB
DROP TABLE dbo.TabelleC

Einfach Copy & Paste in den SSMS und ausführen lassen.
Das Ergebnis sollte wie erwartet sein.

HTH ;-)

Uwe Ricken
db Berater GmbH
http://www.db-berater.de

MCTS: Microsoft SQL Server 2005
MCDBA: Microsoft SQL Server 2005

"Richard Ohl" schrieb im Newsbeitrag
news:
Hallo, ich brauche einen kleinen Denkanschub für T-SQL, bitte. Ich möchte
Daten aus Tabelle A holen und mit Tabelle C verbinden (über Tabelle B n:m
verbunden, oder leer), aber trotzdem nur jeweils _einen_ Datensatz
geliefert
bekommen. Bei Abfragen mehrerer Sàtze aus Tabelle A sollen natürlich
jeweils
ein Datensatz herauskommen.

Tabelle A
a_id a_daten1
1 foo
2 bar
3 lala

Tabelle C
c_id datetime c_daten1
1 2009-01-01 nada
2 2010-01-01 nix

Tabelle B
a_id c_id
1 1
2 1
1 2

Die Abfrage sollte nun alle Datensàtze von A mit dem aktuellsten aus C
verbinden, Ergebnis:
a_id c_id,
1 2
2 1
3 NULL

Kann ich das in dem (Left) Join statement erledigen? Es sieht schwer
machbar
aus, das in einem WHERE zu verpacken, da das ja alle Datensàtze filtern
würde. Grouping mit einem MAX(c.datetime) wird kompliziert, weil ich dann
bei Änderungen ja immer alle Spalten mit gruppieren muss.
Ich habe hier gerade eine Denkblockade...
Vielen Dank für eine Anregung!
Richard
To be stupid, selfish, and have good health are three requirements for
happiness, though if stupidity is lacking, all is lost. -- Gustave
Flaubert

Ähnliche fragen