+ Auf Thema antworten
Ergebnis 1 bis 21 von 21

Thema: Sql - Erm - Rdm

  1. #1

    40 Jahre alt
    626 Beiträge seit 12/2003

    Sql - Erm - Rdm

    Moin Leute ich brauch mal nen Rat von euch.

    kennt jemand ne gute Seite wo SQL auch für blöde erklärt ist? Oder kann mir mal einer erklären was ein Primär und ein Foreign KEy ist, und wo der unterscheid ist. Am besten an 2 ganz simplen blöden Tabellen.

    Dank euch schonmal!

  2. Nach oben    #2

    aus gemachter weltraumreisender
    1.544 Beiträge seit 06/2004
    tabelle 1: wohnliste
    id <- primary key (muss einzigartig sein)
    menschname
    ortid <-- foreign key (wird mit id aus ortsliste verknüpft)

    tabelle 2: ortsliste
    id <- primary key (wird mit ortid in wohnliste verknüpft)
    ortsname
    plz

    ich glaub so war das

  3. Nach oben    #3

    40 Jahre alt
    626 Beiträge seit 12/2003
    der foreign key ist sozusagen ne zusätliche spalte, wenn man es genau nimmt

  4. Nach oben    #4

    aus gemachter weltraumreisender
    1.544 Beiträge seit 06/2004
    der foreign key is der schlüssel aus ner anderen tabelle über den die verknüpfung hergestellt wird, ergo hat der auch ne eigene spalte

  5. Nach oben    #5

    44 Jahre alt
    aus Ulm
    332 Beiträge seit 11/2002
    Zitat Zitat von Haudegen
    kennt jemand ne gute Seite wo SQL auch für blöde erklärt ist?
    Falls die Sache noch aktuell ist, kannst Du Dir mal die Seite http://www.informatik.uni-ulm.de/dbi...1/Skript_DBMS/ anschauen. Das sind die Vorlesungsunterlagen zur Veranstaltung "Datenbanksysteme" der Uni Ulm - meiner Ansicht eines der besten und verständlichsten Vorlesungsskripte, die mir während meiner Studienzeit bislang untergekommen sind. Meiner Meinung nach durchaus für Nicht-Informatiker verständlich.

    Interessant dürften insbesondere die Kapitel 1, 3 und 4 sein. Kapitel 1 und 3 sind allgemeine Einführungen in relationale Datenbanksysteme, Kapitel 4 erläutert die Syntax von SQL-Abfragen am Beispiel des Datenbank-Managementsystem "IBM DB2".

    Zitat Zitat von Haudegen
    Oder kann mir mal einer erklären was ein Primär und ein Foreign KEy ist, und wo der unterscheid ist.
    Ein "Primäry Key" (Primärschlüssel, kurz: "PK") ist eine Spalte in einer Datenbanktabelle, der für jeden Datensatz (also für jede Zeile in der Datenbanktabelle) eindeutig ist.

    Beispiel aus der Praxis: in einer Mitarbeiter-Datenbank nimmt man sinnvollerweise die (in der Regel fortlaufende) "Personalnummer" als PK, nicht z.B. die "Postleitzahl" oder die "Hausnummer" des Mitarbeiters. Denn mit Hausnummer oder Postleitzahl kann man nicht eindeutig auf einen bestimmten Mitarbeiter schließen, mit der Personalnummer dagegen schon.

    Also, kurz gesagt, als PK nimmt man eine Eigenschaft (Attribut, Spalte), die für jeden Datensatz eindeutig ist, d.h. durch Kenntnis des PKs kann man genau einen Datensatz finden (und nicht mehr).

    Der PK kann auch übrigens nicht nur durch eine einzelne Spalte gebildet werden, sondern kann auch aus mehreren Spalten zusammengesetzt sein, z.B. wäre die Kombination aus "Personalnummer" und "Nachnamen" auch eindeutig, aber der PK wäre hier unnötig groß, da ein PK bestehd aus "Personalnummer" bereits eindeutig ist.

    Ein "Foreign Key" (Fremdschlüssel, kurz: "FK") ist etwas, was man braucht, wenn mehr als eine Tabelle im Spiel ist. Bei gescheiten Datenbanstrukturen ist das in der Regel immer der Fall. Ich hoffe, das wird unten am Beispiel deutlich.

    Zitat Zitat von Haudegen
    Am besten an 2 ganz simplen blöden Tabellen.
    Ich versuch's mal. Angenommen Du hast eine Tabelle namens "Mitarbeiter". In der hast Du folgende Attribute gespeichert:

    [center]"Personalnummer" | "Nachname" | "Vorname" | "ProjektNr"[/center]

    • Die Personalnummer machst Du sinnvollerweiße zum PK, denn man vergibt sie eindeutig: Eine Personalnummer referenziert genau einen Datensatz.

    • Die Spalten "Nachname" und "Vorname" enthalten einfach den Nach- bzw. Vornamen des jeweiligen Mitarbeiters.

    • Die Spalte "ProjektNr" enthält die Projektnummer des Projekts, an dem Mitarbeiter beteiligt ist.


    Die Datenbank könnte nun wie folgt mit Datensätzen gefüllt sein:
    [center]
    "Personalnummer" | "Nachname" | "Vorname" | "ProjektNr"
    1 | Maier | Hugo | 2
    2 | Müller | Franz | 3
    3 | Schmid | Karl | 3
    4 | Schwarz | Klaus | 1
    [/center]

    Hier hätten wir also vier Mitarbeiter: Mitarbeiter 1 arbeitet an Projekt 2, Mitarbeiter 2 an Projekt 3, Mitarbeiter 3 ebenfalls an Projekt 3, Mitarbeiter 4 an Projekt 1 mit.

    Wir haben aber noch eine zweite Tabelle. Sie hat den Namen "Projekte" und besitzt folgende Struktur (Spalten):

    [center]"ProjektNr" | "Projektname" | "Etat"[/center]

    • Die ProjektNr ist in dieser Tabelle sinnvollerweiße der PK, denn man vergibt sie ebenfalls eindeutig: Eine ProjektNr referenziert genau einen Projekt-Datensatz.

    • Die Spalten "Projektname" und "Etat" enthalten einfach den Namen des Projekts und den Etat, der dem Projekt zur Verfügung steht.


    Jetzt haben wir hier einige Projekte:
    [center]
    "ProjektNr" | "Projektname" | "Etat"
    1 | Systembetreuung | 12000
    2 | Security | 5000
    3 | Serverräume sauber machen | 20000
    4 | Daumen drehen | 25000
    5 | Heimgehen | 1000
    [/center]

    Du hast nun die beiden einfachen Beispiel-Tabellen...

    Der FK in der Tabelle "Mitarbeiter" stellt quasi ein Bindeglied zur Tabelle "Projekte" her: Hugo Maier arbeitet am Projekt "Security", Franz Müller und Karl Schmid arbeiten am Projekt "Serverräume sauber machen" und Klaus Schwarz ist in der "Systembetreuung" aktiv. Den Projekten "Daumen drehen" und "Heimgehen" sind zur Zeit keine Mitarbeiter zugeordnet: kein Mitarbeiter hat eine "4" oder eine "5" in der Spalte "ProjektNr" stehen.

    Das Datenbanksystem sorgt dafür, dass Du in der Spalte "ProjektNr" in der Tabelle Mitarbeiter auch nur die Werte angeben kannst, für die es auch wirkliche Projekte in der Tabelle "Projekte" gibt - Du könntest hier also keinem Mitarbeiter als "ProjektNr" die "6" eintragen. Du kannst sogar so weit gehen und dem Datenbanksystem ein kaskadierendes Löschen beibringen, z.B. könntest Du es so konfigurieren, dass, wenn ein Projekt gelöscht wird, alle Mitarbeiter, die in diesem Projekt aktiv sind, ebenfalls rausfliegen. Solche Aktionen kann das Datenbanksystem auch in eine Transaktion gekapselt ausführen, aber das führt hier jetzt zu weit.

    Wichtig ist nur für Dich: der FK wird dazu verwendet, auf eine Spalte einer anderen Tabelle (die dort in der Regel PK ist) zu verweisen, um quasi einen Querverweis zwischen mehreren Tabellen herzustellen, denn Hierarchieren hast Du ja in einer relationalen Datenbank keine.

    Du kannst natürlich die berechtigte Frage stellen, was denn nun dagegen spräche, die Beschreibung der Projekte und den Etat einfach in der Tabelle "Mitarbeiter" hinter die Felder "Vorname" und "Nachname" zu klatschen und auf eine separate Tabelle "Projekte" ganz zu verzichten.

    Eine Antwort (es gibt mehrere Gründe, wieso man das nicht macht) liegt nahe: Du riskierst Inkonsistenzen, da Du Projekte, an denen mehrere Leute mitarbeiten (wie hier: "Serverraum sauber machen"), mehrfach auflisten müsstest (-> "Redundanzen"). Wenn nun z.B. am Projekt "Serverraum sauber machen" der Etat gekürzt werden soll, müssten Schreiboperationen in mehreren Datensätzen erfolgen, nämlich in den Datensätzen der beiden Mitarbeiter, die eben an diesem Projekt tätig sind. Wenn nun aber auf Grund eines Programmierfehlers oder eines System-Absturzes nur bei einem Mitarbeiter der Projektetat gekürzt wird, dann hast Du ein inkonsistentes System vorliegen, es ist in einem undefinierten Zustand: welche Etat-Angabe ist jetzt die korrekte?

    Um solche Konstruktionen zu vermeiden, gibt es in der Relationen-Algebra sogenannte "Normalisierungsregeln", durch deren strikte Anwendung man eine Datenbank so strukturieren kann, dass die Attribute "optimal auf die Tabellen verteilt sind". Wie das genau geht, würde auch hier zu weit führen. Das steht aber alles in dem von mir oben geposteten Skript drin, falls Dich die Sache vertiefend interessieren sollte.

    HTH,
    Steffen

  6. Nach oben    #6

    40 Jahre alt
    aus Deutsch-Wagram, Österreich
    21 Beiträge seit 02/2004
    Hi!

    Dein Beitrag ist grundsätzlich richtig und sehr umfangreich, aber ich muss dir in einem Punkt widersprechen:

    Die Personalnummer als PK verwenden.

    Das habe ich bei noch keinem Projekt in der Praxis gemacht, ich verwende ausnahmslos immer interne Nummern, die nach außen hin nicht sichtbar sind (GUIDs z.B.).

    Bei allen Firmen hätte es bis jetzt Probleme mit der Personalnummer gegeben, da - wenn ein Mitarbeiter z.B. die Personalnummer 345 hatte und schon 5 Jahre ausgetreten ist - ein neuer Mitarbeiter diese "Lücke" füllt und diese Personalnummer bekommt. Da steht schnell das ganze System...

    Liebe Grüße,
    Bernd

  7. Nach oben    #7

    44 Jahre alt
    aus Ulm
    332 Beiträge seit 11/2002
    Zitat Zitat von BPodhradsky
    Dein Beitrag ist grundsätzlich richtig und sehr umfangreich, aber ich muss dir in einem Punkt widersprechen:

    Die Personalnummer als PK verwenden.
    Da muss ich Dir vollkommen Recht geben. In meiner Erklärung ging es mir aber auch darum, dass es dem OP möglichst klar wird, was mit der Eindeutigkeit gemeint ist. Da dachte ich, Attribute aus der realen Welt machen es vielleicht deutlicher als interne Nummern.

    Zitat Zitat von BPodhradsky
    Das habe ich bei noch keinem Projekt in der Praxis gemacht, ich verwende ausnahmslos immer interne Nummern, die nach außen hin nicht sichtbar sind (GUIDs z.B.).
    Gut, ich kenne von der Uni her vor allem halt die theoretische Welt. Da ist es in unseren Vorlesungen tatsächlich so üblich, solche Beispiele zu konstruieren - man kann davon halten, was man will. Aber ich stimme Dir zu: in den beiden Praktika, in denen ich mit Datenbanken zu tun hatte, hatten wir stets interne, vom DBMS automatisch inkrementierte Nummern für das PK-Attribut in solchen Fällen - aber dessen war ich mich, als ich auf den OP in diesem Thread antwortete, nicht so richtig bewusst.

    Auf jeden Fall danke für Deinen wertvollen Hinweis!

    Grüße,
    Steffen

  8. Nach oben    #8

    40 Jahre alt
    aus Deutsch-Wagram, Österreich
    21 Beiträge seit 02/2004
    Hi!

    Ich hoffe, du hast meinen Beitrag nicht als "Angriff" verstanden, ich bin beeindruckt, wie viel Information du in diesem Posting rübergebracht hast.

    Wie gesagt, ich wollte das nur anmerken, da dies eben mein Praxisbezug ist. Klar, in einem theoretischen Beispiel ist die Personalnummer okay, eindeutig ist sie ja.

    Nachdem wir aber beide davon ausgehen können, dass die Person, die diese Frage gestellt hat diese Informationen nicht für ein Großprojekt, sondern für schulische Zwecke benötigt, hast du natürlich völlig Recht - aus deinem Beitrag wird klar, dass die ID eindeutig sein muss und in deinem Beispiel ist sie es auch.

    Darf ich fragen, was du studierst (bzw. was für Ziele du mit diesem Studium dann hast)?

    Schönes Wochenende,
    Bernd

  9. Nach oben    #9

    44 Jahre alt
    aus Ulm
    332 Beiträge seit 11/2002
    Zitat Zitat von BPodhradsky
    Ich hoffe, du hast meinen Beitrag nicht als "Angriff" verstanden, ich bin beeindruckt, wie viel Information du in diesem Posting rübergebracht hast.
    Nein, natürlich habe ich Deinen Beitrag nicht als Angriff verstanden - um Gottes Willen, das ist konstruktive Kritik und die ist doch -zumindest von mir- immer erwünscht und wirklich gerne gesehen. Daher ja auch die positiven Karma-Punkte, die ich Dir für Deinen Beitrag -gleich nachdem Du gepostet hattest- gegeben habe. Ich sehe so etwas als Bereicherung, ist mir tausend Mal lieber, als wenn ich z.B. mal richtigen Unsinn verzapfen sollte und mich niemand darauf hinweist.

    Zitat Zitat von BPodhradsky
    Wie gesagt, ich wollte das nur anmerken, da dies eben mein Praxisbezug ist. Klar, in einem theoretischen Beispiel ist die Personalnummer okay, eindeutig ist sie ja.
    Ganz ehrlich: Ich finde es sehr gut von Dir, dass Du das angemerkt hast. Ich will ja auch auf keinen Fall das, was ich hier im Forum (und z.B. auch in Newsgroups und Mailinglisten) schreibe, generell als der Weisheit letzter Schluss rüberbringen, sondern schreibe hier auf Grund meiner eigenen Erfahrungen, die in einigen Bereichen eher theoretisch sind. Wenn mich dann jemand konstruktiv korrigiert, mich auf einen Fehler hinweist oder mir durch eigene Praxiserfahrungen in einem oder mehreren Punkten widerspricht oder ergänzt, ist das aus meiner Sicht doch nur mehr als wünschenswert. Übrigens lerne ich dabei ja auch dazu, und dafür sind sachliche/technische Diskussionen schließlich auch da. Ich fand Dein Posting also sehr gut und sinnvoll und habe es keinesfalls als persönlichen "Angriff" verstanden - im Gegenteil.

    Zitat Zitat von BPodhradsky
    Darf ich fragen, was du studierst (bzw. was für Ziele du mit diesem Studium dann hast)?
    Ich studiere Informatik mit Nebenfach Physik an der Uni Ulm und bin zur Zeit in meinem 9. Semester. Ich werde Ende dieses bzw. Anfang nächstes Semester an meine Diplomarbeit gehen, wobei ich hier noch schauen muss, in welche Richtung ich gehe bzw. welche Abteilung zum entsprechenden Zeitpunkt interessante Themen anbietet. Was ich dann danach mache, hängt auch ein wenig davon ab, welchen Einblick ich in eine Abteilung im Rahmen meiner Arbeit bekomme. Meine Interessen liegen eher im Bereich "Kommunikationsnetze", aber Themen der theoretischen Informatik finde ich prinzipiell auch nicht uninteressant.

    Mit anderen Worten: ganz konkret weiß ich noch nicht, wie es nach dem Studium genau weitergeht. Ich würde gerne noch an der (oder einer anderen) Uni bleiben (als Mitarbeiter in einer Abteilung), um ein wenig Einblick in die Forschung zu bekommen. Aber dies ist bei der jetzigen finanziellen Situation der Hochschulen (bzw. aller öffentlichen Institutionen), sagen wir, "nicht einfach". Wenn Abteilungen an den Universitäten eine besimmte Anzahl von Stellen im Laufe der nächsten Jahre einsparen müssen (und das ist zumindest hier der Fall), dann ist es einfach schwierig, da rein zu kommen.

    Datenbanken und Anwendungsentwicklung kenne ich eben hauptsächlich aus zwei Praktika (also verhältnismäßig kleine Projekte im Vergleich zu dem, was in der Industrie läuft) und einer Vorlesung, ich muss aber ehrlich sagen, dass ich jetzt auch nicht so der Programmier-Guru bin.

    Darf ich fragen, was Du machst bzw. woher Du Deine Erfahrungen hast?

    Zitat Zitat von BPodhradsky
    Schönes Wochenende,
    Bernd
    Danke, ebenfalls!

    Viele Grüße,
    Steffen

  10. Nach oben    #10

    40 Jahre alt
    aus Deutsch-Wagram, Österreich
    21 Beiträge seit 02/2004
    Hallo!

    Interessant, du kommst also eher aus der universitären (theoretischen) Seite.

    Ich bin selbstständig tätig (Softwareentwicklung und -beratung) und habe bei diversen Großprojekten Erfahrungen in diesem Bereich sammeln und erweitern können.

    Schönes Wochenende,
    Bernd

  11. Nach oben    #11

    40 Jahre alt
    626 Beiträge seit 12/2003
    danke übrigens euch beiden

  12. Nach oben    #12

    40 Jahre alt
    626 Beiträge seit 12/2003
    oh man ich komm an einer Stelle nicht weiter obwohl ich jetzt alles außer Join Commands gepaukt hab.

    Also gegeben ne Tabelle Mitarbeiter, die Üblichen Attribute (Adrese usw.) PK ist Personal_Code und FK ist "Arbeitet in Abteilung" mit Preferenc auf die Tabelle Abteilung genauer gesagt da auf das Attribut AbteilungsNummer (logischerweise halt auch PK).

    Die Tabelle Abteilung hat noch das Attribut Bezeichnung und Abteilungsleiter. Das Attribut Abteilungsleiter ist FK mit der Preferenc Personal_Code aus der Mitarbeiter Tabelle.

    Frage: gibt es eine Abteilung ohne Mitarbeiter?!

    eigentlich schon oder? ich meine man könnte doch einfach nen leeren Datensatz nehmen oder nicht?! Wenn das nciht geht dann muss jede Abteilung eien Leiter haben weil ja halt dem FK IMMER ein PK zugeweisen wird oder nicht?

    BOAR NÖRVT SQL!

  13. Nach oben    #13

    40 Jahre alt
    aus Deutsch-Wagram, Österreich
    21 Beiträge seit 02/2004
    Hallo!

    Die grundsätzliche Situation habe ich verstanden, aber was du benötigst noch nicht ganz.

    Benötigst du ein SQL-Skript, das dir die Anzahl der Abteilungen zurückgibt (oder ein True / False, ob es eine Abteilung ohne Mitarbeiter gibt)?

    Oder möchtest du wissen, ob das Datenbankmodell zulässt, dass in einer Abteilung keine Mitarbeiter sind? Wenn ja, dann lautet die Antwort ja, denn es kann in der Abteilungstabelle ein Datensatz stehen, auf den bei den Mitarbeitern nicht referenziert wird!

    Beispiel:

    Abteilungen:
    1 - Support
    2 - Verkauf

    Mitarbeiter
    1 - Klaus - 1 (arbeitet im Support)
    2 - Matthias - 1 (arbeitet im Support)

    Wie man sieht, ist in der Abteilung Verkauf kein Mitarbeiter.

    Liebe Grüße,
    Bernd

  14. Nach oben    #14

    40 Jahre alt
    626 Beiträge seit 12/2003
    ups da habe ich mich letztes mal schon bei der Frage vertan, die frage lautete ob es in jederAbteilung einen Abteilungsleiter gibt.

    Die Frage bezieht sich nur darauf ob es grundsätzlich möglich wäre, wenn nicht wie man es ändern müsste.

  15. Nach oben    #15

    44 Jahre alt
    aus Ulm
    332 Beiträge seit 11/2002
    Zitat Zitat von Haudegen
    ups da habe ich mich letztes mal schon bei der Frage vertan, die frage lautete ob es in jederAbteilung einen Abteilungsleiter gibt.

    Die Frage bezieht sich nur darauf ob es grundsätzlich möglich wäre, wenn nicht wie man es ändern müsste.
    Es ist grundsätzlich möglich, nach diesem Modell eine Abteilung ohne Abteilungsleiter anzulegen. Es hängt genau genommen davon ab, ob Du NULL-Werte in der Spalte "Abteilungsleiter" in der Tabelle "Abteilungen" zulässt oder nicht.

    Wenn Du NULL-Werte erlaubst (kannst Du in allen mir bekannten Datenbanksystemen z.B. beim Erstellen der Tabelle angeben), dann kannst Du als Abteilungsleiter statt des "Personal_Code" (aus der Tabelle "Mitarbeiter") den Wert NULL angeben. Wenn Du aber keine NULL-Werte erlaubst, muss in jedem Abteilungsdatensatz in der Spalte "Abteilungsleiter" in jedem Fall ein "Personal_Code" stehen (also ein die ID eines Mitarbeiters). In diesem Fall hätten dann zwangsläufig alle Abteilungen auch einen Abteilungsleiter.

    HTH,
    Steffen

  16. Nach oben    #16

    40 Jahre alt
    626 Beiträge seit 12/2003
    noch ne Frage an die experten ob ich das so richtig gemacht habe, ich bin mir nciht ganz sicher was das "counten" angeht...

    Gegeben seien die Relationen Haus, Person und WohntIn, welche wie nachfolgend angegeben definiert sind. Geben Sie zu den angegebenen Fragen die zugehörige SQL-Anfrage an.

    Haus : HNr(PK), Strasse, Nr, PLZ, Ort, Stockwerke, Wohnungszahl, Baujahr
    Person: Name(PK); Vorname(PK), Geburtstag(PK), Groesse, Haarfarbe, Gehalt
    WohntIn: HNr(PK), Name, Vorname, Geburtstag

    Geben Sie die Adressen der Häuser an, in denen (mindestens) eine blonde Person wohnt.

    select Strase, HNr, PLZ, Ort
    from Haus
    wehre Haus.HNr=wohntIn.HNr
    and wohntIn.Name=Person.Name
    and wohntIn.Vormane=Person.Vorname
    and wohntIn.Geburtstag=Person.Geburtstag
    and Person.Haarfarbe=`blond´
    having count(Person.Haarfarbe)>1
    group by PLZ

    und die Aufgabe dazu kreig ich net ganz hin

    Geben Sie die Liste aller Häuser aus und geben Sie in der Liste jeweils
    Hausidentifikationsnummer (HNR) und die Anzahl der im Haus lebenden Personen an (d.h. zweispaltige Tabelle wird erzeugt).

  17. Nach oben    #17

    aus Nicht weit vom Rhein
    757 Beiträge seit 11/2002
    Endlich mal eine wirklich vernünftige Diskussion bei der "Ungenauigkeiten" akzeptiert werden und sachlich diskutiert werden.

    Es geht nichts über menshcliche Reife.

  18. Nach oben    #18

    44 Jahre alt
    aus Ulm
    332 Beiträge seit 11/2002
    Zitat Zitat von Haudegen
    noch ne Frage an die experten ob ich das so richtig gemacht habe, ich bin mir nciht ganz sicher was das "counten" angeht...

    Gegeben seien die Relationen Haus, Person und WohntIn, welche wie nachfolgend angegeben definiert sind. Geben Sie zu den angegebenen Fragen die zugehörige SQL-Anfrage an.

    Haus : HNr(PK), Strasse, Nr, PLZ, Ort, Stockwerke, Wohnungszahl, Baujahr
    Person: Name(PK); Vorname(PK), Geburtstag(PK), Groesse, Haarfarbe, Gehalt
    WohntIn: HNr(PK), Name, Vorname, Geburtstag
    Ich habe mir erlaubt, diese Struktur etwas zu vereinfachen (macht meiner Meinung nach die SQL-Querys etwas übersichtlicher), in dem ich für die Person eine ID als PK angelegt habe. Ist außerdem auch sinnvoll, weil Dein Modell ja zwei Personen, die den selben Vornamen, den selben Nachnamen und das selbe Geburtsdatum haben, nicht zulässt (gut, solche konstruierten Fälle sollen hier nicht stören, aber es macht halt die Anfragen etwas einfacher).

    Bei mir sieht die Struktur jetzt so aus:
    • Tabelle Haus: HausID(PK), Strasse, Hausnummer, PLZ, Ort, Stockwerke, Wohnungszahl, Baujahr
    • Tabelle Person: PersonID(PK), Name, Vorname, Geburtstag, Groesse, Haarfarbe, Gehalt
    • Tabelle WohntIn: PersonID(PK), HausID(PK); PersonID REFERENCES Person.PersonID, HausID REFERENCES Haus.HausID

    Die "REFERENCES"-Angaben stellen die Fremdschlüssel dar, wenn Du dazu noch Fragen hast, stell' sie hier einfach.


    Das von Dir (und mir) verwendete Datenmodell unterstützt wegen der separaten "WohntIn"-Tabelle auch "n:m"-Beziehungen, d.h. eine Person kann ich mehreren Häusern wohnen (was durchaus Sinn macht) und ein Haus kann von mehreren Personen bewohnt werden (was ja unbedingt sinnvoll ist, wenn Häuser schon mehrere Stockwerke haben können).

    Ich habe Dir hier die Tabellenstruktur und hier die Ausgabe der Tabellen mit Beispieldaten abgelegt.

    Zitat Zitat von Haudegen
    Geben Sie die Adressen der Häuser an, in denen (mindestens) eine blonde Person wohnt.

    select Strase, HNr, PLZ, Ort
    from Haus
    wehre Haus.HNr=wohntIn.HNr
    and wohntIn.Name=Person.Name
    and wohntIn.Vormane=Person.Vorname
    and wohntIn.Geburtstag=Person.Geburtstag
    and Person.Haarfarbe=`blond´
    having count(Person.Haarfarbe)>1
    group by PLZ

    und die Aufgabe dazu kreig ich net ganz hin
    Du musst zunächst erst mal die Tabellen abrufen, die Du brauchst. Du brauchst ja hier nicht nur "Haus", sondern auch "WohntIn" und "Person". Das ist quasi Deine JOIN-Operation (Du kannst in den meisten SQL-Systemen auch den JOIN als solchen hinschreiben).

    Übrigens, wenn Du nur machst:

    SELECT *
    FROM Haus, WohntIn, Person;


    dann erhältst Du quasi jede erdenkliche Kombination aller Datensätze der drei Tabellen, man nennt das auch das kartesische Produkt, siehe auch hier.

    In der Regel will man aber nur Teile dieses kartesischen Produkts haben, z.B. die, wo die Werte aus "WohntIn.HausID" mit "Haus.HausID" und die Werte aus "WohntIn.PersonID" mit Person.PersonID" übereinstimmen (also in diesem Fall die Leute mit den Wohnungen, in denen sie wohnen). Wenn man also:

    SELECT *
    FROM Haus, WohntIn, Person
    WHERE Haus.HausID=WohntIn.HausID
    AND WohntIn.PersonID=Person.PersonID;


    dann gibt es schon mal wesentlich weniger Ergebnistupel, nämlich diese hier. So weit, so gut. Du willst jetzt die Adressen aller Häuser haben, in denen mindestens eine blonde Person wohnt...

    Nimm doch einfach mal die oben genannte Operation, die Dir alle Personen und ihre Wohnsituation auflistet. Was spräche jetzt hier dagegen, einfach nur die Ergebnisse davon zu nehmen, die die Haarfarbe "blond" drinstehen haben, also so:

    SELECT *
    FROM Haus, WohntIn, Person
    WHERE Haus.HausID=WohntIn.HausID
    AND WohntIn.PersonID=Person.PersonID
    AND Person.Haarfarbe='blond';


    Das ergibt dann das hier. Du hast also nun alle blonden Personen mit ihren Häusern aufgelistet. Du siehst, Du hast eigentlich damit auch schon alle Häuser, in denen mindestens eine blonde Person wohnt (bist also nicht mehr weit von dem entfernt, was Du haben möchtest). Du willst aber nur die Adressen der Häuser (und nicht die ganzen Daten der Personen), also machst Du noch eine Projektion (also Deine Ergebnistablle "schmäler"):

    SELECT Haus.Strasse, Haus.Hausnummer, Haus.PLZ, Haus.Ort
    FROM Haus, WohntIn, Person
    WHERE Haus.HausID=WohntIn.HausID
    AND WohntIn.PersonID=Person.PersonID
    AND Person.Haarfarbe='blond';


    Das ergibt dann dieses hier. Das liegt jetzt ja schon ganz nahe an dem, was Du haben willst. Jetzt ist nur noch das Problem, dass Häuser, in denen "n" blonde Personen wohnen, nicht nur ein Mal, sondern "n" Mal genannt werden.

    Hier kannst Du nun aber die Duplikate mit der SQL-Anweisung DISTINCT eliminieren. Mit anderen Worten: Die Anfrage

    SELECT DISTINCT Haus.Strasse, Haus.Hausnummer, Haus.PLZ, Haus.Ort
    FROM Haus, WohntIn, Person
    WHERE Haus.HausID=WohntIn.HausID
    AND WohntIn.PersonID=Person.PersonID
    AND Person.Haarfarbe='blond';


    sollte das Gewünschte leisten. Die Ausgabe findest Du hier.

    Zähloperationen scheint man für diese Anfrage also nicht zu brauchen, und ich sehe momentan auch nicht den Sinn darin, sie zu verwenden, wenn man die Sache nicht unnötig kompliziert mahen will... ;-)


    Zitat Zitat von Haudegen
    Geben Sie die Liste aller Häuser aus und geben Sie in der Liste jeweils
    Hausidentifikationsnummer (HNR) und die Anzahl der im Haus lebenden Personen an (d.h. zweispaltige Tabelle wird erzeugt).
    Hier müssen wir aber nun definitiv zählen.

    Wir wollen haben: Alle Häuser und die Anzahl der darin lebenden Personen. Zunächst mal würde ich sagen, schauen wir uns den JOIN über die Häuser- und die WohntIn-Tabelle an, die Personen-Tabelle brauchen wir ja hier gar nicht, da wir hier ja keine Eigenschaften der Personen spezifizieren wollen (wie z.B. beim letzten Beispiel die Haarfarbe):

    SELECT *
    FROM Haus, WohntIn
    WHERE Haus.HausID=WohntIn.HausID;


    Das hier liefert uns also, wie Du hier sehen kannst, Häuser, in denen Leute wohnen, und gleichzeitig die IDs dieser Bewohner. Du siehst schon, dass ein Haus mit drei Bewohnern drei Mal gelistet wird, ein Haus mit zwei Bewohnern zwei Mal, usw...

    Wir wollen nun zählen. Aber nicht irgend etwas, sondern wie oft jedes Haus (jede HausID) genannt wird. Also klappen wir die Ergebnisse quasi zusammen (und zwar alle, die die selbe HausID haben, werden zu einem Ergebnis zusammengefasst). Somit steht jede HausID nur noch ein Mal da:

    SELECT *
    FROM Haus, WohntIn
    WHERE Haus.HausID=WohntIn.HausID
    GROUP BY Haus.HausID;


    Das Ergebnis siehst Du wiederum hier. Das allein hilft aber noch nichts. Wir wollen ja zählen, also schreiben wir hin:

    SELECT *, COUNT(*) AS 'Anzahl Bewohner'
    FROM Haus, WohntIn
    WHERE Haus.HausID=WohntIn.HausID
    GROUP BY Haus.HausID;


    Obwohl wir jetzt nur drei Ergebniszeilen da stehen haben (nach dem "GROUP BY"), steigt der COUNT-Operator nun tatsächlich in die einzelnen zusammengeklappten Ergebnisse hinein ab und zählt sie.

    Was Du erhältst, ist schon ziemlich nahe an dem, was Du haben möchtest, siehe hier.

    Du möchtest nur die HausID haben, also führen wir wieder die bekannte Projektion durch:

    SELECT Haus.HausID, COUNT(*) AS 'Anzahl Bewohner'
    FROM Haus, WohntIn
    WHERE Haus.HausID=WohntIn.HausID
    GROUP BY Haus.HausID;


    Das Ergebnis findest Du hier.

    Sollte soweit tun, aber...

    (Fortsetzung folgt)

  19. Nach oben    #19

    44 Jahre alt
    aus Ulm
    332 Beiträge seit 11/2002
    (Fortsetzung; habe das Posting in zwei Beiträge zerteilt, da zu lang)

    ...es gibt noch ein Problem: Wenn Du jetzt ein Haus hast, in dem niemand wohnt, dann wird das nicht aufgelistet, da in der WHERE-Klausel kein Treffer erzeugt wird und es damit gar nicht in der Liste der Ergebnistupel auftaucht.

    Fügen wir also ein weiteres Haus ein:

    INSERT INTO Haus
    VALUES (4,'Trampelpfad',15,'12345','Neustadt',3,5,1938);


    und ordnen wir diesem Haus keine Bewohner zu.

    Nun müssten wir die WHERE-Klausel modifizieren, sodass auch leere Häuser ausgegeben werden. Das ist aber ohne "JOIN" nicht ganz einfach.

    Aus diesem Grund führe ich ihn nun doch noch ein. Das, was wir vorher mit

    SELECT *
    FROM Haus, WohntIn
    WHERE Haus.HausID=WohntIn.HausID;


    gemacht haben, geht genauso mit:

    SELECT *
    FROM Haus
    JOIN WohntIn
    ON Haus.HausID=WohntIn.HausID;


    Du erhältst in beiden Fällen die selbe Ausgabe. Es gibt nur manche Datenbanksysteme, die "JOIN" nicht kennen, und man es daher wie oben machen muss.

    Wenn Du jetzt aber mal statt "JOIN" schreibst "LEFT OUTER JOIN":

    SELECT *
    FROM Haus
    LEFT OUTER JOIN WohntIn
    ON Haus.HausID=WohntIn.HausID;


    dann ist das unbewohnte Haus tatsächlich mit dabei, wie Du hier siehst.

    Das Ergebnis von vorher können wir jetzt auch schreiben:

    SELECT Haus.HausID, COUNT(*) AS 'Anzahl Bewohner'
    FROM Haus
    JOIN WohntIn
    ON Haus.HausID=WohntIn.HausID
    GROUP BY Haus.HausID;


    Auch hier machen wir nun aus dem "JOIN" einen "LEFT OUTER JOIN":

    SELECT Haus.HausID, COUNT(*) AS 'Anzahl Bewohner'
    FROM Haus
    LEFT OUTER JOIN WohntIn
    ON Haus.HausID=WohntIn.HausID
    GROUP BY Haus.HausID;


    und erhalten nun das hier.

    Moment, irgend etwas stimmt noch nicht: Im Haus mit der HausID=4 soll angeblich eine Person wohnen, dabei wohnt da doch gar niemand... Woran liegt's? Ganz einfach: COUNT(*) zählt die Ergebnistupel. Wenn Du Dir das Beispiel darüber, also das hier:

    SELECT *
    FROM Haus
    LEFT OUTER JOIN WohntIn
    ON Haus.HausID=WohntIn.HausID;


    anschaust, dann wirst Du feststellen, dass hier in der Tat ja eine Ergebniszeile für das Haus mit der HausID=4 da ist. Nichts Anderes zählt unser COUNT(*).

    Wie kommen wir zum richtigen Wert (in diesem Fall: 0)? Wir müssen nicht zwangsläufig die Ergebnistupel zählen, sondern können auch zählen, wie viele Werte in einer bestimmten Spalte vorhanden sind. Schaust Du Dir die Ausgabe von dem oben genannten Beispiel nochmals an (siehe hier), dann siehst Du, dass beim Haus mit der HausID=4 in den beiden rechten Spalten "NULL" steht. Diese beiden Spalten kommen aus der Tabelle "WohntIn", und hier gibt es in der Spalte "HausID" in der Tat keinen korrespondierenden Eintrag zur ganz linken Spalte ("HausID" aus der Tabelle "Haus"). Bei unseren Anfragen am Anfang und bei einem "JOIN" wäre die Zeile also gar nicht dazugekommen. Hier haben wir aber den "LEFT OUTER JOIN" verwendet, und dieser nimmt in jedem Fall alle Häuser, und schreibt für "WohntIn" eben "NULL" hin, wenn niemand in einem bestimmten Haus wohnt.

    Nun zählt "COUNT" solche NULL-Werte nicht mit. Und genau das können wir ausnutzen, wenn wir nun die Bewohner richtig zählen wollen. Wir dürfen dann keinen "COUNT(*)" absetzen, da der ja alle Tupel zählt (denn für das Haus mit der HausID=4 gibt es ja auch ein Ergebnistupel), sondern wir müssen zählen, wie viele "Antworten" (die nicht "NULL" heißen) in der Spalte "WohntIn.HausID" stehen (also in der rechten "HausID"-Spalte) - bezogen auf die gruppierten "Haus.HausIDs".

    Wir schreiben also:

    SELECT Haus.HausID, COUNT(WohntIn.HausID) AS 'Anzahl Bewohner'
    FROM Haus
    LEFT OUTER JOIN WohntIn
    ON Haus.HausID=WohntIn.HausID
    GROUP BY Haus.HausID;


    und erhalten das Gewünschte, wie Du hier siehst.


    Ich hoffe, dass das Ganze nicht zu komplex war und halbwegs verständlich rüber kam. Ansonsten solltest Du in dem von mir genannten Datenbankenskript auch viele Beispiele zu solchen Anfragen finden bzw. hier einfach nochmals nachfragen.

    In meinen Beispielen habe ich teilweise die Abkürzungen gesetzt, also statt:

    SELECT Haus.HausID, COUNT(WohntIn.HausID) AS 'Anzahl Bewohner'
    FROM Haus
    LEFT OUTER JOIN WohntIn
    ON Haus.HausID=WohntIn.HausID
    GROUP BY Haus.HausID;


    habe ich bei den programmierten Beispielen geschrieben:

    SELECT H.HausID, COUNT(W.HausID) AS 'Anzahl Bewohner'
    FROM Haus AS H
    LEFT OUTER JOIN WohntIn AS W
    ON H.HausID=W.HausID
    GROUP BY H.HausID;


    Das ist genau dasselbe.

    Getestet bzw. die Outputs erzeugt habe ich mit "MySQL-4.0.20" (mit "InnoDB-Tabellen" wegen der FOREIGN KEYs) und testweise auch unter "IBM DB2/SUN 7.1.0". Falls Du den MySQL-Datenbank-Dump haben willst, um eine eigene Testdatenbank anzulegen, lass es mich wissen.

    Falls jemand Fehler findet oder Verbesserungsvorschläge-/hinweise hat, bin ich natürlich jederzeit dankbar!

    Schöne Feiertage!

    Gruß,
    Steffen

  20. Nach oben    #20

    40 Jahre alt
    aus Deutsch-Wagram, Österreich
    21 Beiträge seit 02/2004
    Hallo!

    Keine Fehler entdeckt, aber dass du mySQL verwendest ist mir als Softwareentwickler ein Graus . Ein Datenbanksystem, das keine Transactions unterstützt und sehr lange keine Sub-Selects unterstützt hat, ist für mich kein Datenbanksystem.

    Nichts für ungut, ich weiß schon, dass es für diese Zwecke sehr gut ist, hoffe du erkennst meinen Scherz und siehst es nicht als negative Kritik.

    Vielen Dank übrigens für deinen langen und ausführlichen Beitrag, bewundernswert!

    Fachlich - soweit ich das "überflogen" habe - alles korrekt.

    Liebe Grüße,
    Bernd

  21. Nach oben    #21

    44 Jahre alt
    aus Ulm
    332 Beiträge seit 11/2002
    Zitat Zitat von BPodhradsky
    Hallo!

    Keine Fehler entdeckt, aber dass du mySQL verwendest ist mir als Softwareentwickler ein Graus .
    :-)

    Zitat Zitat von BPodhradsky
    Ein Datenbanksystem, das keine Transactions unterstützt und sehr lange keine Sub-Selects unterstützt hat, ist für mich kein Datenbanksystem.
    Dass die Version 4.0.x, die ich gestern, als ich den Artikel schrieb, zur Verfügung hatte, keine Sub-Selects kann, habe ich übrigens auch erst beim Schreiben des Artikels bemerkt, als ich meinte, eine Anfrage mal spaßeshalber mittels Sub-Select lösen zu müssen... Ich dachte echt, das kann nicht wahr sein... Sub-Querys gibt's also tatsächlich erst ab Version 4.1.x in MySQL...

    Was die Transactions und die referentielle Integrität betrifft, habe ich, als ich letztes Semester mein Web-Engineering-Praktikum (an der Uni) machte, auch nicht schlecht gestaunt, als doch MySQL tatsächlich nichts, aber auch gar nichts von "FOREIGN KEYs" (und allem, was dazugehört) wissen wollte. Da lernt man in der Datenbankenvorlesung (dort haben wir mit "DB2" gearbeitet), dass "ACID" das Wesentliche an Datenbanksystemen ist, und dann macht man drei Semester später ein Praktikum (Zieloberfläche der zu programmierenden Web-Anwendung: MySQL und Tomcat bzw. Apache+PHP4) und stellt mit Entsetzen fest, dass MySQL nichts davon kann...

    Wie ist das eigentlich mit InnoDB-Tabellen in MySQL? Hintergrund meiner Frage: Wir haben dann in unserem Praktikum "Web-Engineering", weil wir referentielle Integrität, kaskadierendes Löschen, usw. haben wollten (eben ein halbwegs sauber umgesetztes Datenmodell), statt der standardmäßig verwendeten "MyISAM"-Tabellen die "InnoDB"-Tabellen verwendet (wir mussten dazu eine neuere MySQL-Version kompilieren, da die uns auf dem Zielserver zur Verfügung gestellt Version keine "InnoDB"-Unterstützung einkompiliert hatte).

    Sind denn wenigstens bei "InnoDB"-Tabellen mittlerweile richtig gekapstelte Transaktionen in MySQL, virtueller Einbenutzerbetrieb, usw. möglich oder wird das dem Benutzer nur vorgetäuscht? Zumindest in kleinen Tests (arg viel Zeit hatte ich für die Experimente damals nicht) sah es so aus, als würde da tatsächlich transaktionell abgearbeitet - aber vielleicht waren meine Tests auch nicht "ausführlich" genug, um auf Probleme zu stoßen. ;-)

    Zitat Zitat von BPodhradsky
    Nichts für ungut, ich weiß schon, dass es für diese Zwecke sehr gut ist, hoffe du erkennst meinen Scherz und siehst es nicht als negative Kritik.
    Mach' Dir da mal keine Sorgen... ;-)

    Vor allem steht MySQL halt kostenlos sowie für die wichtigsten Plattformen zur Verfügung (evtl. hat ja der OP sogar selber Zugriff auf eine MySQL-DB zum Testen) - und ich musste nicht erst installieren, ich habe einfach die DB von meinem Praktikum hergenommen...

    Ich habe an der Uni auch schon mit PostgreSQL gearbeitet, fand das eigentlich auch recht gut. Es konnte auf jeden Fall mit referentieller Integrität schon vor Jahren etwas anfangen. Allerdings hatten seinerzeit die Windows-User in meinem Team Probleme, es mit Cygwin auf Windows 9x-Maschinen zum Laufen zu kriegen.

    Was wird denn im Allgemeinen in größeren Software-Projekten Deiner Erfahrung nach zur Zeit so eingesetzt - DB2, Oracle und evtl. noch MS-SQL nehme ich an, oder?

    Zitat Zitat von BPodhradsky
    Vielen Dank übrigens für deinen langen und ausführlichen Beitrag, bewundernswert!

    Fachlich - soweit ich das "überflogen" habe - alles korrekt.
    Danke Dir auf jeden Fall fürs Durchlesen und Deine Kommentare dazu!

    So, jetzt aber: frohe Weihnachten und schöne Festtage!

    Viele Grüße,
    Steffen

+ Auf Thema antworten

Lesezeichen für Sql - Erm - Rdm

Lesezeichen