Komplexe MsSQL-Abfrage in einer stored procedure
Michael Huhn
- datenbank
Folgendes Problem: ich habe aus einem Select ein RecordSet mit IDs. Jetzt will ich aus einem anderen Table, der im JOIN des ersten Selects nicht benutzt wurde, alle Einträge zurückgeben, der Table soll jedoch ein zusätzliches Feld blnPossible haben, das auf true gesetzt wird, wenn die ID des Eintrags in dem ersten SELECT vorkam.
also:
SELECT irgendwas FROM Table1 JOIN Table2
gibt 10 und 11 zurück.
Table3 enthält Einträge mit den IDs 10,11 und 12. Jetzt will ich alle Einträge aus Table3 zurückgeben, allerdings soll eine zusätzliche Column blnPossible bei 10 und 11 auf true gesetzt sein, bei 12 auf false. Wie mache ich das?? Bei CREATE VIEW kommt jedes mal ein Fehler, ich benutze MsSQL 7, das scheint das nicht zu unterstützen. Kann ich ein dreifaches JOIN machen? Ich habe kein php oder so zur Verfügung, nur MsSQL.
Hallo,
kannst Du mal kurz die Struktur Deiner Tabellen zugänglich machen. Ich denke, ich könnte Dir helfen.
Gruß Frank
sorry, die Benennung ist etwas "schwierig". ich habe
1.)tblAttributeSet
mit den Feldern:
tblAttributeSetId
intItemId
2.)tblAttributeSetAttribute
mit Feldern:
tblAttributeSetAttribute
intAttributeSetId
intAttributeId
3.) tblAttribute
mit:
tblAttributeId
strTitle
Dann habe ich ein SELECT tblAttributeSetAttribute.intAttributeId über ein JOIN von Table 1 und Table 2 gemacht mit
JOIN ON
tblAttributeSetAttribute.intAttributeSetId = tblAttributeSet.tblAttributeSetId
gemacht. Ich will jetzt alle Einträge aus tblAttribute haben und möchte an einem zusätzlichen Feld blnPossible ablesen können, ob diese Row in dem vorherigen Select vorkam. Sorry, ich kann es nicht einfacher ausdrücken aber es wäre wirklich super, wenn du mir helfen könntest :)
Gruß
Michael
Hallo Michael,
Dein Problem ist in der Tat schwer zu verstehen. Wenn ich Deine Tabellenstruktur richtig interpretiere, kannst Du mit folgendem Statement die Daten aus alllen 3 Tabellen in einer Abfrage holen:
SELECT * FROM tblAttributeSet,tblAttributeSetAttribute,tblAttribute WHERE intAttributeSetId = tblAttributeSetId AND
intAttributeId = tblAttributeId
Dann hättest Du alle Informationen da. Vielleicht kannst Du die WHERE-Bedingung noch um bestimmte Filter erweitern, die Du brauchst.
Hoffe, das bringt Dich auf die richtige Schiene. Wenn ich Dich falsch verstanden habe, schicke mir mal die statements, die Du bisher auf die DB losgelassen hast.
HTH
Gruß Frank
Hallo Frank,
das hiflt mir schon mal weiter, danke. Mein Problem ist aber jetzt, dass ich aus dem dritten Table tblAttribute alle Einträge will, eine zusätzliche Spalte mit einer Funktion soll allerdings entprechend des SELECT-Statements, das du mir gegeben hast, auf true gesetzt werden. Hast du dazu noch ne Idee? Oder ist das Problem noch unklar?
Hallo Michael,
... Oder ist das Problem noch unklar?
Irgendwie schon. Gibt es in dieser Tabelle eine Spalte, in die der Wert geschrieben werden soll? Was ist das eigentliche Ziel=
Gruß Frank
Irgendwie schon. Gibt es in dieser Tabelle eine Spalte, in die der Wert geschrieben werden soll?
Nein, die müsste ich erst anlegen. Also entweder zur laufzeit anlegen, ne temporäre Tabelle erstellen oder einen view, aber view scheint ja nicht zu gehen
Was ist das eigentliche Ziel=
Ich habe zwei Tables wo Infos über Attribute drinstehen. Aus den beiden Tables bekomme ich per SELECT einige IDs zurückgegeben. Jetzt will ich ALLE Attribute haben und will beim Ergebnis für jeden Eintrag abfragen können, ob er in dem ersten SELECT war.
Äquivalentes Problem: Ich habe einen Table mit alles Bundesbürgern. Ich will jetzt eine Liste mit allen erstellen und in der Liste arbeitslose Frauen markieren. Dazu habe ich zwei Tables: "Frauen" und "Arbeitslos". Ein Select auf diese beiden Tables gibt mir 350.000 IDs zurück, die den IDs in der "Bundesbürger"-Tabelle entsprechen. Wie bekomme ich jetzt eine Liste mit allen Bundesbürgern, bei der ich für jeden eintrag auslesen kann, ob der Bürger eine arbeitslose Frau ist, ohne 80 Mio. SELECTs machen zu müssen?
Gruß
Michael
Hallo Michael,
Eigentlich soltest Du mit dem Join nur die 350.000 Einträge zurückbekommen, die Du als Ergebnis der ersten Abfrage erhältst.
Um bei Deinem beispiel zu bleiben:
Wenn das SELECT auf die beiden Tabellen "Frauen" und "arbeitslos" genau die Menge ID's an Bundesbürgern liefert, dann kommen auch nur die zugehörigen Infos der Bundesbürger dazu. Zusätzliche Datensätze kommen nich in das Resultset.
HTH
Gruß Frank
PS: Falls ich immer noch etwas nicht verstanden habe, schicke mal den Code Deiner Procedure.
Hi Michael
SELECT irgendwas FROM Table1 JOIN Table2
gibt 10 und 11 zurück.
Table3 enthält Einträge mit den IDs 10,11 und 12. Jetzt will ich alle Einträge aus Table3 zurückgeben, allerdings soll eine zusätzliche Column blnPossible bei 10 und 11 auf true gesetzt sein, bei 12 auf false. Wie mache ich das?? Bei CREATE VIEW kommt jedes mal ein Fehler, ich benutze MsSQL 7, das scheint das nicht zu unterstützen. Kann ich ein dreifaches JOIN machen?
Nur mal ein ungetesteter Versuch, eher pseudocode als reales SQL
Select a.feld, is_null(c.feld) -- gibt es sowas wie is_null in MSSql?
from a
left outer join b on (a.key = b.key)
left outer join c on (b.key = c.key) -- Verknüpfung aus deiner 2. Query
where deine bedingungen
Das müsste dir alles aus b geben. Dazu ist c.feld nur gesetzt,
also nicht null falls eine Verknüfung zwischen a und b und von
b nach c existiert. Der left outer join sagt, es ist mir
egal ob in b od c was drinsteht, gib mir einfach alles was dazu
passt und sonst null. Mit is_null (od wie das in MSSQL auch heisst)
setzt du dann noch deinen Boolean.
Gruss Daniela
Hallo Daniela,
Select a.feld, is_null(c.feld) -- gibt es sowas wie is_null in MSSql?
from a
left outer join b on (a.key = b.key)
left outer join c on (b.key = c.key) -- Verknüpfung aus deiner 2. Query
where deine bedingungen
Das klingt irgendwie logisch, wenn ich es auch nicht komplett verstehe. ISNULL gibt es, ISNULL ( check_expression , replacement_value ) gibt replacement_value zurück, wenn check_expression = NULL ist.
Ich verstehe allerdings nicht, was c.feld sein soll. Was für ein Feld soll ich da angeben?
Gruß
Michael
Hi Michael
Ich verstehe allerdings nicht, was c.feld sein soll. Was für ein Feld soll ich da angeben?
Das ist dein Key aus Tabelle 3, dem Select was du angegeben hast (die
mit dem Feld irgendwas), der müsste ja gefüllt sein wenn er vorhanden ist
und sonst NULL.
Gruss Daniela
Hallo
leider funktioniert das Skript so nicht:
SELECT
tblAttribute.strTitle,
tblAttribute.intAttributeGroupId,
tblAttribute.tblAttributeId,
ISNULL(tblAttributeSet.tblAttributeSetId,1) AS blnPossible
FROM
tblAttribute
LEFT OUTER JOIN
tblAttributeSetAttribute
ON
(tblAttributeSetAttribute.intAttributeId = tblAttribute.tblAttributeId)
LEFT OUTER JOIN
tblAttributeSet
ON
(tblAttributeSetAttribute.intAttributeSetId = tblAttributeSet.tblAttributeSetId)
WHERE tblAttributeSetAttribute.intAttributeId = 6 ORDER BY tblAttribute.intAttributeGroupId,tblAttributeSetAttribute.intAttributeId
Wenn ich "6" als Wert reingebe, bekomme ich nur das Attribut 6 zurück :-( Tut mir leid, ich weiß, dass die TableNamen das ganze sehr unübersichtlich machen.
Trotzdem noch eine Idee?
Hallo
lanngsam wird die Sache deutlicher. Zwei Sachen fallen mir auf:
1. Du solltest wohl für Dein Problem statt des OUTER JOIN einen INNER JOIN verwenden.
2. Du kannst statt des Wertes "6" folgendes einfügen:
WHERE feld IN (SELECT * FROM ...) welches Dir Deinbe Schlüsselliste liefert.
HTH
Gruß Frank
Hallo
ein Kollege ist gerade wiedergekommen und hat's mit erklärt. Was ich gesucht hatte, war folgendes:
CREATE PROCEDURE
dbo.uspGetAttributesByAttributes
@strAttributeIds varchar(500) AS
DECLARE
@strSQL varchar(1000)
SET
@strSQL = '
SELECT
tblAttribute.strTitle,
tblAttribute.intAttributeGroupId,
tblAttribute.tblAttributeId,
CASE
WHEN intAttributeId IS NULL THEN 0
ELSE 1
END AS blnIsPossible
FROM
tblAttributeSetAttribute
JOIN tblAttributeSet ON tblAttributeSetId = intAttributeSetId
RIGHT JOIN tblAttribute ON tblAttributeId = intAttributeId
WHERE ('
DECLARE
@strWhere varchar(300)
EXEC
spb_Split @strAttributeIds, 'tblAttributeSetAttribute.intAttributeId', 1, @strWhere OUTPUT
SET
@strSQL = @strSQL + @strWhere + ')
OR
tblAttributeSetAttribute.intAttributeId IS NULL
ORDER BY tblAttribute.intAttributeGroupId,tblAttributeSetAttribute.intAttributeId'
EXEC (@strSQL)
GO
und das funktioniert :)
thx a lot
Gruß
mhuhn