none
SQL-Abfrage mit WHERE funktioniert nicht. Nur HAVING...

    Allgemeine Diskussion

  • Hallo zusammen!

    Ich erstelle gerade eine Auswertung einer IBM iSeries DB2-Datenbank unter Verwendung von Access und dem iSeries Client Access ODBC Treiber.

    Nun bin ich auf ein ganz merkwürdiges Verhalten gestossen: Ich möchte eine Tabelle nach Belegart "EK" filtern:

    SELECT KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG, KD_YAK.AKPREI, KD_YAK.AKBEL
    FROM KD_YAK
    WHERE KD_YAK.AKARTN="BOH38200B" AND KD_YAK.AKARTV="300" AND KD_YAK.AKBEL="EK";

    Bei dieser Abfrage werden inN AKBEL aber ebenfalls andere belegarten ausgegeben (z.B. RE).

    Gestalte ich dieselbe Abfrage unter Verwendung von Aggregatfunktionen, funktioniert es:

    SELECT KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG, KD_YAK.AKPREI, KD_YAK.AKBEL
    FROM KD_YAK
    GROUP BY KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG, KD_YAK.AKPREI, KD_YAK.AKBEL
    HAVING KD_YAK.AKARTN="BOH38200B" AND KD_YAK.AKARTV="300" AND KD_YAK.AKBEL="EK";

    Ich arbeite nun seit mehreren Jahren in dieser Konstellation und habe etwas derartiges noch nciht erlebt. Der Fehler tritt im übrigen unter Office 2007 und 2010 auf. Hat vielleicht jemand eine Erklärung dafür??

    Viele Grüße,

    Thies

     

    Freitag, 5. November 2010 10:09

Alle Antworten

  • Hallo,

    countryhiller wrote:

    Nun bin ich auf ein ganz merkwürdiges Verhalten gestossen: Ich möchte
    eine Tabelle nach Belegart "EK" filtern:
    SELECT KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG, KD_YAK.AKPREI, KD_YAK.AKBEL
    FROM KD_YAK
    WHERE KD_YAK.AKARTN="BOH38200B" AND KD_YAK.AKARTV="300" AND KD_YAK.AKBEL="EK";

    Bei dieser Abfrage werden inN AKBEL aber ebenfalls andere belegarten
    ausgegeben (z.B. RE).

    Ist KD_YAK eine Tabelle oder Abfrage? Falls letzteres, wie sieht diese aus?

    Gestalte ich dieselbe Abfrage unter Verwendung von Aggregatfunktionen,
    funktioniert es:

    SELECT KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG, KD_YAK.AKPREI, KD_YAK.AKBEL
    FROM KD_YAK
    GROUP BY KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG, KD_YAK.AKPREI, KD_YAK.AKBEL
    HAVING KD_YAK.AKARTN="BOH38200B" AND KD_YAK.AKARTV="300" AND KD_YAK.AKBEL="EK";

    Der Unterschied zwischen WHERE und HAVING ist, dass HAVING auf das Ergebnis der Abfrage angewendet wird, was bei Aggregatfunktionen unerlaesslich ist, z.B. HAVING Sum(xy) > 0.

    In deinem Fall muss WHERE reichen. Evtl. ist ein Index im BE kaputt? Bau diesen auf DB2 nochmal auf und binde danach die Tabelle nochmal ein.

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Freitag, 5. November 2010 10:22
    Moderator
  • Hallo Peter,

    vielen Dank für die Antwort.

    KD_YAK ist eine per ODBC verknüpfte "Tabelle" auf der AS400 (Physical File). Es gibt hier also bei Physical Files, soweit ich weiß, keinen Index. Das Query-Tool auf der AS400 liefert das korrekte Ergebnis. Was meinst du mit BE?

    Gruß, Thies

    Freitag, 5. November 2010 13:00
  • Hallo,

    countryhiller wrote:

    KD_YAK ist eine per ODBC verknüpfte "Tabelle" auf der AS400 (Physical
    File). Es gibt hier also bei Physical Files, soweit ich weiß, keinen
    Index. Das Query-Tool auf der AS400 liefert das korrekte Ergebnis. Was
    meinst du mit BE?

    BE = Backend. Bez. "Physical File", du hattest im OP DB2 geschrieben,
    deshalb ging ich von einer DB mit Tabelle und Index aus. Wenn dahinter
    keine DB steht, sondern irgendwelche ISAM Files, kann ich leider auch nur
    raten. Als Ursache scheint mir der ODBC-Treiber am wahrscheinlichsten.
    Jedenfalls ist dein SQL-Befehl garantiert nicht die Ursache.

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Freitag, 5. November 2010 13:51
    Moderator
  • Hallo!

    countryhiller schrieb:

    KD_YAK ist eine per ODBC verknüpfte "Tabelle" auf der AS400 (Physical File). Es gibt hier also bei Physical Files, soweit ich weiß, keinen Index.

    Hast du schon einmal per ODBC-Trace geprüft, welche SQL-Anweisungen
    zur AS400 gelangen?

    Möglicherweise wird der Where-Teil per ODBC übertragen und das Group
    By übernimmt bereits das Access-FE womit es dann eventuell auch den
    gesamten Having-Teil übernimmt.

    Was passiert bei folgender Anweisung:

    SELECT
        KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG,
        KD_YAK.AKPREI, KD_YAK.AKBEL
    FROM
        KD_YAK
    WHERE
        KD_YAK.AKARTN='BOH38200B'
        AND KD_YAK.AKARTV='300'
        AND KD_YAK.AKBEL='EK';
    GROUP BY
        KD_YAK.AKARTN, KD_YAK.AKARTV, KD_YAK.AKLTAG,
        KD_YAK.AKPREI, KD_YAK.AKBEL

    Würde die "normale" SQL-Anweisung als Pass-Through-Abfrage
    funktionieren?

    Steht Access eigentlich ein eindeutiges Feld zur Datensatzerkennung
    zur Verfügung?
    Normalerweise (zumindest nach meinen bisherigen Beobachtungen bei
    Jet-Abfragen auf ODBC-verknüpfte Tabellen) läuft der Datentransfer per
    ODBC nämlich so ab, dass zuerst nur die ID-Werte mit dem Filter-Teil
    angefordert werden und dann zu diesen ID-Werten die DS (vollständiger
    Select-Teil) abgeholt werden.

    mfg
    Josef

    Freitag, 5. November 2010 14:11
  • Hallo zusammen!

    Vorweg: Das Problem ist gelöst. Die Ursache war der zusammengesetzte Primärschlüssel, der mehr aus mehr als 10 Feldern besteht (Access kann nur 10). Lasse ich die Definition weg, funktioniert es einwandfrei. Ich weiß, dass ich ohne Definition des Primärschlüssels keine Daten per ODBC in Access verändern kann (das schließt UPDATE-Abfrage mit nur lesendem Zugriff ebenfalls ein). Kann es weitere Konsequenzen geben?

    Im Trace ist erkennbar, dass auch hier zunächst der PK abgefragt mit Filter abgefragt wird. In dieser Reihenfolge wäre es natürlich vorstellbar, dass zu den ID-Werten mehrere Einträge passen. Allerdings habe ich in meinem nicht vollständigen PK schon eine Vorgangsnummer, die natürgemäß vor Vorgang "EK" zu "RE" unterschiedlich ist. Warum diese Enträge dennoch geliefert werden ist für mich immernoch fraglich..

    Ja, die von Josef vorgeschlagene Abfrage funktioniert ebenfalls (liefert nur Ergebnisse mit "EK"). In Anbetracht der Tatsache, dass die Abfrage ohne GROUP BY das falsche Ergebnis liefert, verstehe ich nun ganz und gar nicht, wie es sein kann, dass das Ergbnis nach dem Hinzufügen der Aggregatfunktion keine RE-Einträge liefert!?!?!!

    Als Fazit würde ich nun erstmal ziehen, dass ich nur den kompletten oder keinen Primärschlüssel hinterlege. In Hinblick auf die unkomplizierte Nutzung von UPDATE-Anweisungen würde mich allerdings brennend interessieren, wie dieses Verhalten vermieden werden kann. Offenbar genügt die Eindeutigkeit des hinterlegten PK im Zusammenhang mit dem erwarteten Ergebnis nicht (Stichwort Vorgangsnummer). Sollte ich hier etwas noch nicht ganz verstanden haben, würde ich mich über einen Hinweis sehr freuen.

    Vielen Dank soweit!

    Viele Grüße,

    Thies

    Montag, 8. November 2010 11:30
  • Hallo,

    countryhiller wrote:

    Vorweg: Das Problem ist gelöst. Die Ursache war der zusammengesetzte Primärschlüssel, der mehr aus mehr
    als 10 Feldern besteht (Access kann nur 10).

    Jo, siehe OH: Spezifikationen.

    Ich weiß, dass ich ohne Definition des Primärschlüssels keine Daten per
    ODBC in Access verändern kann (das schließt UPDATE-Abfrage mit nur
    lesendem Zugriff ebenfalls ein). Kann es weitere Konsequenzen geben?

    Nicht, dass ich wuesste. Die fehlende Moeglichkeit, Aktualisierungen
    vorzunehmen, reicht schon. Du koenntest dem entgegenwirken, indem du im
    Backend ein Identity (Autowert) anlegst - sofern das in deinem "Physical
    File" moeglich ist - und dieses beim Verknuepfen als PK verwendest, denn
    damit haettest du einen PK mit nur einem Feld.

    Als Fazit würde ich nun erstmal ziehen, dass ich nur den kompletten oder
    keinen Primärschlüssel hinterlege. In Hinblick auf die unkomplizierte
    Nutzung von UPDATE-Anweisungen würde mich allerdings brennend
    interessieren, wie dieses Verhalten vermieden werden kann.

    s.o.

    Gruss - Peter


    Mitglied im http://www.dbdev.org
    FAQ: http://www.donkarl.com

    Dienstag, 9. November 2010 01:03
    Moderator
  • Hallo Peter

    KD_YAK ist eine per ODBC verknüpfte "Tabelle" auf der AS400 (Physical
    File). Es gibt hier also bei Physical Files, soweit ich wei�?, keinen
    Index. Das Query-Tool auf der AS400 liefert das korrekte Ergebnis. Was
    meinst du mit BE?

    BE = Backend. Bez. "Physical File", du hattest im OP DB2 geschrieben,
    deshalb ging ich von einer DB mit Tabelle und Index aus. Wenn dahinter
    keine DB steht, sondern irgendwelche ISAM Files, kann ich leider auch nur
    raten. Als Ursache scheint mir der ODBC-Treiber am wahrscheinlichsten.
    Jedenfalls ist dein SQL-Befehl garantiert nicht die Ursache.

    Wenn es ein Zugriff über ODBC ist, dann gibt es auch bei ISAM Files nichts zu raten, ODBC ist da ziemlich strikt, was unterstützt werden muss. Ich denke übrigens er meint mit physical file eher, dass die DB dort abgespeichert ist. Auf WHERE und HAVING sollte das keinen Einfluss haben, sonst ist es ein Fehler im ODBC Treiber. Im allgemeinen ist es alledings sicherer, bei gruppierten Abfragen generell Having statt WHERE zu verwenden, auch wenn man nicht die gruppierten Felder einschränkt. Was nämlich genau gruppiert wird, merkt man erst, wenn man einen ODBC Trace startet. Da wird oft mehr gruppiert, als man erwartet, speziell, wenn man Reports verwendet.
     
    Gruss
    Henry
    Montag, 15. November 2010 05:16