Verzwicktes Abfrageproblem

  • Allgemein

Es gibt 35 Antworten in diesem Thema. Der letzte Beitrag () ist von ErfinderDesRades.

    Verzwicktes Abfrageproblem

    Hallo,
    erstmal sorrsy für den Thread-Titel, aber mir ist keiner eingefallen, der das Problem beschreibt.

    Es handelt sich um eine Abfrage, die den aktuellen Status des Abzufragenden Objekts gleich mit gibt.

    Ich habe 3 Tabellen:

    Quellcode

    1. [Akten]
    2. Aktennr
    3. Bezeichnung
    4. [Historie]
    5. AktenNr
    6. Datum
    7. Wer
    8. AktionID
    9. [Aktion]
    10. ID
    11. Bezeichnung (Ausleihen/Zurückgeben)

    Nun möchte ich eine Abfrage generieren, die mir eine Liste aller Akten ausgibt und zu jeder Akte den aktuellen Status, sprich, ob sie Ausgegeben oder Zurückgegeben ist.

    Den Status der Einzelnen Akte bekomme ich mittels:

    SQL-Abfrage

    1. SELECT AktionID
    2. FROM Historie
    3. WHERE (AktenNr = @AktenNr) AND (Datum =
    4. (SELECT MAX(Datum) AS Datum
    5. FROM Historie AS Historie_1
    6. WHERE (AktenNr= @AktenNr) ))

    Aber wie kommt man nun an eine Liste aller Akten mit dem aktuellen Status?

    Für eine Hilfestellung wäre ich dankbar.
    also in einem typDataset würdest du zunächst alle Akten in die Akten-DataTable laden.
    Dann alle Historien dieser Akten, aber nur mit dem Max(Datum) in die Historien-DataTable
    Jo, und mit einer berechneten Spalte könnte man auch die AktionID in die Akten-DataTable hineinholen.

    Der Witz dabei wäre, dass du die Akten dann im typDataset auch bearbeiten könntest, und alle Änderungen mit der dafür vorgesehenen Standard-Methode rückspeichern - mit einem einzigen Befehl.

    Aber typisiertes Dataset lehnst du ja anscheinend ab.
    Vielleicht hilft dir nen simpler JOIN schon weiter?

    SQL-Abfrage

    1. SELECT Akten.Aktennr, Akten.Bezeichnung, Historie.Datum, Historie.Wer, Aktion.Bezeichnung
    2. FROM Aktion
    3. RIGHT JOIN (Akten
    4. LEFT JOIN Historie
    5. ON Akten.Aktennr = Historie.AktenNr)
    6. ON Aktion.ID = Historie.AktionID
    7. WHERE Akten.Aktennr=@AktenNr AND
    8. (Historie.Datum = (
    9. SELECT MAX(Historie_1.Datum)
    10. FROM Historie AS Historie_1
    11. WHERE AktenNr= @AktenNr));


    Das ist nu aus dem Kopf so runter geschrieben anhand der von dir genannten Tabellen und Spaltennamen... Und dem was du sehen willst.
    Würde Tabellen nu nicht über nen WHERE verknüpfen, sondern nen Join nehmen. Gerade wenn du ne Historie hast und zu ner Akte noch GARKEINE Info darüber in der Historie ist, ob sie Ausgeliehen wurde oder nicht. Wenn da kein Satz ist, würde ja dann nix mehr angezeigt oder? Via RIGHT bzw. LEFT JOIN kriegst die Datensätze trotzdem noch... Da Akten führend ist und die restlichen Infos nur ergänzt werden... Sonst isses halt NULL XD
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „MemoAnMichSelbst“ ()

    Memos Hinweis auf Akten, zu denen vlt. kein einziger Historie-Datensatz vorliegt, würde mich dazu führen, beim Anlegen einer Akte immer auch einen Historien-Datensatz dazu anzulegen, mit dem Status "im Haus" oderso.


    Im TypDataset würdich glaub sogar eine umgekehrte Relation Historie->Akte einrichten, mit als ForeignKey eine berechnete Spalte, die immer das Max-Datum berechnet. So könnteman von jeder Akte direkt auf den aktuellen Historie-Datensatz zugreifen.
    (Dassis aber eine neue Idee von mir, und noch nie getestet - ich glaub beim Zufügen dieser DataRow-Pärchen wird man was hacken müssen ;))
    Ok, das hatt mich weiter gebracht, die Abfrage funktioniert so ... aber da wirft sich schon das nächste Problem auf, ich muss die Tabelle Akten noch auf Unterakten erweitern:

    Quellcode

    1. [Akten]
    2. Aktennr
    3. UnteraktenNr
    4. Bezeichnung
    5. [Historie]
    6. AktenNr
    7. Unteraktennr
    8. Datum
    9. Wer
    10. AktionID
    11. [Aktion]
    12. ID
    13. Bezeichnung (Ausleihen/Zurückgeben)

    Nun Benötige ich von der angegebenen AktenNr alle Unterakten mit Status ... komplizierte Geschichte :(
    Naja, kannst du ja auch via JOIN entsprechend anbinden. Alles halb so wild.
    Mit JOINs solltest dich eh beschäftigen, wenn du datenbänklern willst (und das auch mal direkt auf ner DB und nicht nur via Studio).
    Nen JOIN ist nen sehr mächtiges Werkzeug und nur halb so kompliziert wie die Meisten denken ^^
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Halb so kompliziert wie die Meisten denken ... ist wohl immernoch zu komliziert für mich ... Ich hab nu das Ergebnis, dass er mir 2 Unterakten ausgibt, wie gewünscht, aber beide mit dem selben Datum. Eine Ergänzung um das Feld UnteraktenNr gruppiert den rest also nur.
    Ich probier die Abfragen schon immer direkt auf der DB aus :)
    Was hast du denn so für Unterakten?
    Oder ist das nur nen stupides Feld in der Tabelle und keine eigene (zu verknüpfende) Tabelle?
    Ich bin nicht so der abstrakt denkende Mensch. Ich muss immer irgendwie was vor mir haben um mir vorstellen zu können was du dir bastelst.

    Ich denke du hast ne Tabelle
    [Unterakten]
    ID
    Bezeichnung

    oder sowas?

    ODER Sind Aktennummer und Unteraktennummer ZUSAMMEN der Primärschlüssel bzw. der Fremdschlüssel?
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Die Frage ist... Was ist ne Unterakte?! ^^ Ich kann damit gerade nicht so viel anfangen.
    Können ganze Akten UND nur Unterakten ausgeliehen werden?

    Dann wäre für mich eine Unterakte ne eigene Tabelle und jede Akte besteht aus mehreren Unterakten.
    Und keine Akte kann ausgeliehen werden, sondern nur eine Unterakte...
    Und wenn ne ganze Akte ausgeliehen ist, ist halt jede Unterakte der Akte ausgeliehen.

    War das verständlich? XD
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    Es können Unterakten Ausgeliehen werden. Es gibt immer mindestens eine Unterakte zu jeder Akte. Wenn von Akte ABC die Unterakte 1 voll ist, wied die Unterakte 2 angelegt. usw.
    Wird eine neue Akte angelegt, wird auch gleich die Unterakte 1 angelegt.

    Ich hoffe ich konnte das einigermaßen verständlich rüber bringen.

    Danke!

    vlt. hilft es, dass der PK bei den Akten aus Akte und Unterakte besteht.

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „nemesis“ ()

    Du bekommst ein Problem wenn du die Unteraktennummer und Aktennummer zusammen in einer Tabelle mit Datum hast und das letzte Datum suchst...

    Gehen wir mal von folgenden aus...

    Tester A leiht sich AkteA UnterakteA am 10.10.2012 aus...
    Tester A leiht sich AkteA UnterakteB am 11.10.2012 aus...
    Hat somit beide Unterakten... Da duch nach dem MAXDatum suchst... Wirst du aber nur die am 11.10.2012 ausgeliehene Unterakte B finden ;)
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    genau das meinte ich, ich benötige das aktuellste Datum der Kombination Akte-Unterakte :)

    also so gehts:

    SQL-Abfrage

    1. SELECT * FROM
    2. (
    3. SELECT Akten.Aktennr, Akten.UnteraketnNr Akten.Bezeichnung, Historie.Datum, Historie.Wer, Aktion.Bezeichnung
    4. FROM Aktion
    5. RIGHT JOIN (Akten
    6. LEFT JOIN Historie
    7. ON Akten.Aktennr = Historie.AktenNr)
    8. ON Aktion.ID = Historie.AktionID
    9. WHERE Akten.Aktennr=@AktenNr AND
    10. (Historie.Datum = (
    11. SELECT MAX(Historie_1.Datum)
    12. FROM Historie AS Historie_1
    13. WHERE AktenNr= @AktenNr));
    14. )
    15. WHERE UnteraktenNr=@Unteraktennr


    aber ob das so elegant ist ... ;)

    ne, geht doch nicht, gibt das falsche Datum zurück :(

    Dieser Beitrag wurde bereits 2 mal editiert, zuletzt von „nemesis“ ()

    Ich würds ja so lösen:

    SQL-Abfrage

    1. SELECT Akten.Aktennr, Historie.UnteraktenNr, Akten.Bezeichnung, Historie.Datum, Historie.Wer, Aktion.Bezeichnung
    2. FROM Aktion
    3. RIGHT JOIN (Akten
    4. LEFT JOIN Historie
    5. ON (Akten.Aktennr = Historie.AktenNr)
    6. AND Akten.Unteraktennr = Historie.UnteraktenNr)
    7. ON Aktion.ID = Historie.AktionID
    8. WHERE (Akten.Aktennr=@AktenNr
    9. AND Historie.Datum=(
    10. SELECT MAX(Historie_1.Datum)
    11. FROM Historie AS Historie_1
    12. WHERE AktenNr=Akten.Aktennr
    13. AND UnteraktenNr = Akten.UnteraktenNr));
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    Es war einmal ein kleiner Bär... der wollte eine Geschichte hörn... Da erzählte ihm seine Mutti:
    ... Nun solltest es selber wissen. :'D
    tja, aber an dieser lausigen Abfrage kannst du nix editieren.

    Oder es kommt Irrwitz dabei heraus, etwa:

    jmd kommt, möchte eine Akte ausleihen. Du fährst die Abfrage ab, und findest, sie ist im Haus.
    Du händigst die Akte aus.
    Dafür musst du einen Historie-Datensatz zufügen.
    Dann stimmt aber deine Abfrage nicht mehr.
    Also Abfrage neu laden

    => viel zuviel DB-Traffic.

    im typDataset hätteste eine HistorieRow zugefügt und wärst fertig, u.U. sogar ohne diese in die DB zu speichern. Weil du hättest eine Speicher-Routine, die alle Änderungen aller Tabellen auf einmal wegspeichert (seien es nun 1000 Änderungen, oder nur eine einzige DataRow), wohingegen du nun für jedes Abspeichern jeder einzelnen Tabelle oder sogar einzelner Datensätze bis zu 3 Methoden wirst schreiben dürfen: eine für INSERT, eine für UPDATE, eine für DELETE.

    Also du werkelst komplett am Konzept von Ado.Net vorbei.
    Das war doch die Abfrage, die ich für das Dataset wollte, um damit eine Datatable befüllen zu können. Was genau verstehst du unter einem Typisierten Dataset? Ich glaube wir reden aneinander vorbei. Ich verstehe darunter, dass sich darin eine Datatable befindet, die den Inhalt liefert, den ich so auch auf der Form haben möchte. D.H. ich mache die ganzen Abfragen in den TableAdapters und fülle damit Datatables. Diese lasse ich dann in z.B. ein Datagridview ausgeben.