Access Tabellen: ein Textfeld und ein Zahl Feld mit Join verbinden

  • VB.NET

Es gibt 14 Antworten in diesem Thema. Der letzte Beitrag () ist von petaod.

    Access Tabellen: ein Textfeld und ein Zahl Feld mit Join verbinden

    Ich habe eine Access Datei in der befinden sich unter anderem zwei Tabellen die möchte ich gerne gemeinsam abfragen.

    In der ersten Tabelle sind die Umsätze drinn, in der Zweiten sind die Stammdaten.
    Soll heißen erste Tabelle die Menge des verkauften Produktes (z.B. 3 Flaschen Bier)
    In der zweiten Tabelle stehen die EK Werte (z.B. 1 Flasche kostet im Einkauf 0,50€)

    wie kann ich beide Tabellen verknüpfen damit ich den Wareneinkaufswert vom Tag anzeigen kann.
    In diesem Fall also 3 * 0,50 = 1,50
    Das natürlich für alle Datensätze des ausgewählten Tages.

    Problem ist das die Artikelnummer in der einen Tabelle eine vierstellige Zahl ist und in der andern Tabelle ein 8 stellige Text
    z.B. Artikelnummer = 1001 als Zahl
    Artikel Nummer = 01011001 als Text (in diese Tabelle werden immer 0101 vor die eigentliche Artikelnummer gestellt - warum auch immer)

    geht das überhaupt mit einer SQL Abfrage oder muss ich alle Datensätze einzeln durchlaufen lassen und bei jedem Datensatz in der anderen Tabelle den EK Preis raus suchen?

    SQL-Abfrage

    1. SELECT tabelle2.Artikel FROM tabelle1
    2. JOIN tabelle2 ON CInt((MID(tabelle1.Artikel,5,99)) = tabelle2.Artikel
    3. WHERE tabelle1.Artikel='1010101010'

    SQL-Abfrage

    1. SELECT tabelle2.Artikel
    2. WHERE tabelle1.Artikel='1010101010'
    3. AND CInt(MID(tabelle1.Artikel,5,99)) = tabelle2.Artikel
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Danke für die Antwort
    das mit dem cInt(MID(..... war die richtige Idee.

    aber wie bekomme ich den gesamten EK für den ganzen Tag?
    Es sind ja viel verschiedene Artikel, mit verschiedenen Verkaufszahlen.
    Das das Ergebniss nur für einen Tag gezeigt wird hab ich hiermit geschafft.

    VB.NET-Quellcode

    1. WHERE Tabelle1.ArbeitsDatum LIKE '" & MyDatum LIKE & "'"


    VB.NET-Quellcode

    1. Dim SqlString as String
    2. SqlString = "SELECT "
    3. SqlString += "Tabelle1.Artikel_ID, "
    4. SqlString += "Tabelle1.Anzahl, "
    5. SqlString += "Tabelle1.GPreis, "
    6. SqlString += "Tabelle1.MwStProzent, "
    7. SqlString += "Tabelle1.ArbeitsDatum, "
    8. SqlString += "Tabelle2.ArtikelNr, "
    9. SqlString += "Tabelle2.EKPreis "
    10. SqlString += "FROM Tabelle1 "
    11. SqlString += "INNER JOIN Artikel ON Tabelle2.ArtikelNr = CINT(MID(Tabelle1.Artikel_ID,5,99)) "
    12. SqlString += "WHERE Tabelle1.Arbeitsdatum LIKE '" & MyDatum & "'"


    Nun hab ich eine Tabelle in der stehen die einzelnen Datensätze aus Tabelle1 und in den letzten beiden Spalten die ArtikelNr und der EK Preis aus Tabelle2.

    Ich hab noch eine Berechnete Spalte hinzugefügt Anzahl * EKPreis.
    Das ist dann der gesamt EK für einen Datensatz.

    Und diesen gesamt EK möchte ich summieren um den Gesamt EK für diesen Tag zu erhalten.

    Ich hab die Daten in einem DatagridView angezeigt um die Daten überprüfen zu können. Brauchen tue ich das DGV nicht, ist nur um Ergebnisse zu überprüfen. Da es sich um 468 Datensätze handelt bekomme ich immer einen Überlauf aber es werden genug Daten angezeigt um den SqlString zu prüfen. (Aber das nur am Rande)

    frifri schrieb:

    Das das Ergebniss nur für einen Tag gezeigt wird hab ich hiermit geschafft...
    Code-Horror mal in Sql ;)
    Ein Datum ist ein Datum, und kein String - das gilt auch in Sql.
    Der Like-Operator ist für String-Verarbeitung, Datumse gleicht man mit <, >, =, <> ab.
    Falls du deine Datumspalte wirklich als Text hinterlegt hast, hast du einen Modellierungs-Fehler in deim Datenmodell, den du unbedingt ausmerzen solltest.

    Auch die Benamung deiner Tabellen ist 100% tödlich.

    Und welcher Wahnsinnige hat verzapft, dass die ArtikelNummern als String angelegt werden, noch dazu mit unterschiedlicher Länge?
    Das schlägt dem Faß die Krone ins Gesicht.

    SQL-Abfrage

    1. Tabelle2.ArtikelNr = CINT(MID(Tabelle1.Artikel_ID,5,99))
    soll ich nu lachen oder weinen? :D ;(
    Offensichtlich ist Tabelle2.ArtikelNr dann wieder eine INT - Zahl? 8|

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

    Ja, da ist beim Datenmodell einiges schiefgelaufen, aber wie ich das verstanden habe, kann der TE da nix für, er muss nur auf die bestehenden Daten jetzt seine Lösung draufsetzen. Der Horror eines jeden Coders, hab ich selbst viel zu oft mitmachen müssen.
    Ich kann mir sogar vorstellen, wie das mit den Artikelnummern "passiert" sein könnte - auch wenns keine Rechtfertigung sein soll: In der Regel haben Handelsartikel ja eine eindeutige EAN. Diese besteht nicht aus "irgendeiner zufälligen Zahl", sondern enthält vornehmlich einen Länder- und einen Herstellercode, lediglich die letzten x Stellen sind dann vom Hersteller frei wählbar. Vermutlich ist das hier der Grund. In der einen Tabelle steht dann die Hersteller-eigene Artikelnummer, in der anderen Tabelle findet sich der komplette EAN-Code, also mit vorangestelltem Länder- und Herstellercode. Und da diese EAN vermutlich eine bestimmte Länge haben "muss", führende Nullen aber in der Regel bei einem numerischen Wert aber nicht angezeigt werden, hatte sich der Datenbankdesigner wohl gedacht, das einfach in einen String zu klatschen.

    Sowas ähnliches hab ich auch mal vorgefunden. Da ging es auch um Artikelnummern für die Produktion. Nach der Fertigung auf einer Maschine sollten die Bauteile mit Etiketten versehen werden, auf die diese Nummer als Barcode gedruckt wird. Und mein Vorgänger, der die Datenbank dazu verzapft hatte (das ist noch "harmlos" formuliert) hat - neben vielen anderen Designfehlern - auch in einer der Tabellen, aber nicht in allen, die Artikelnummer zu eben diesem Zweck mit führenden Nullen versehen in einem String verpackt. Jede Kreuztabellenabfrage - und davon kamen nachträglich einige hinzu - wird somit jedes Mal zu einem Abenteuer, zumal auch noch keine der Tabellen eine Art fortlaufende ID hat und die Verknüpfung ausschließlich über die Artikelnummer funktioniert. (Das Happy End meiner Geschichte: Ich darf mich jetzt richtig austoben, also nicht nur die Anwendung von VC++ 6.0 nach .NET migrieren, sondern komplett neu designen - inklusive Datenmodell.)
    Weltherrschaft erlangen: 1%
    Ist dein Problem erledigt? -> Dann markiere das Thema bitte entsprechend.
    Waren Beiträge dieser Diskussion dabei hilfreich? -> Dann klick dort jeweils auf den Hilfreich-Button.
    Danke.
    Also eine ArtikelNr als String aufzusetzen ist nicht ungewöhnlich. Wie du sagst: Oft sinds ja gar keine Nummern, sondern sind String-Codes, die nach iwelchen Regeln gebildet werden.

    Ich denk, der Fehler ist, in der DB eine Beziehung nicht einzurichten, wo tatsächlich eben doch eine Beziehung besteht inne Wirklichkeit.
    Hätte man (Beispiel post#1) die Relation zw. Verkäufe-Tabelle und Produkt-Tabelle richtig modelliert mit einer 1:n - Relation, dann hätte die DB von vornherein schon damals erzwungen, dass PrimKey und ForeignKey denselben Datentyp haben, und es wäre später zur Laufzeit auch ühaupt nicht möglich gewesen, Verkäufe einzuspeichern, deren Artikelnummer nicht den ArtikelNummern der Produkt-Tabelle entstammt.
    (Und so ganz nebenbei geht erheblich Sql-Performance flöten, weil Sql-Provider sind mordsmäßig optimiert, wenns drum geht, Standard-Relationen auszuwerten - und das geht glaub bei Cint(Mid(Artikel_id, 5, 99) verloren.)

    ErfinderDesRades schrieb:

    Und dein DB-Designer hat die Tabellen wirklich Tabelle1, Tabelle2 genannt, und Tabelle1.ArbeitsDatum als String angelegt?


    nicht mein DB-Designer - is halt so
    ja hat er - nicht zu ändern

    Tabelle1.ArbeitsDatum ist ein Datum. lt Access jedenfalls aber bei = mekkert das VB.Net Programm. Bei LIKE nicht.
    "Datentypen in Kriterienausdruck unverträglich."
    Dim MyDatum As Date

    und nun kannst du über verschüttete Milch weinen oder was konstruktives beisteuern.
    liebe Grüße
    frifri
    Also konstruktiv:

    frifri schrieb:

    "Datentypen in Kriterienausdruck unverträglich."
    Das kann auch von falscher Kriterien-Syntax herrühren, du müsstest mal zeigen, welchen Filter genau du gesetzt hattest, als die Exception kam.
    Weil wenn Access aussagt, es sei ein Datum, dann stimmt das meist.

    Datumse muss man mit invarianter Kultur formatieren, und müssen glaub in '#' gequoted sein.
    Ich hab das dann mal so gelöst.
    falls es jemanden Interessiert.

    VB.NET-Quellcode

    1. con.Open()
    2. Private Function gesEK(ByVal MyDatum As Date) As Double
    3. Dim SqlString As String
    4. Dim anzahl As Integer = 0
    5. 'Erst mal prüfen ob überhaupt Daten da sind
    6. cmd.CommandText = "Select count(*) FROM Tabelle1 where ArbeitsDatum LIKE '" & MyDatum & "'"
    7. anzahl = cmd.ExecuteScalar()
    8. If anzahl > 1 Then
    9. SqlString = "SELECT "
    10. SqlString += "SUM(Tabelle1.Anzahl * Tabelle2.EkPreis) "
    11. SqlString += "FROM Tabelle1 "
    12. SqlString += "INNER JOIN Tabelle2 ON int(MID(Tabelle1.Artikel_ID,5)) = Tabelle2.ArtikelNr "
    13. SqlString += "WHERE Tabelle1.Arbeitsdatum LIKE '" & MyDatum & "'"
    14. cmd.CommandText = SqlString
    15. gesEK = cmd.ExecuteScalar
    16. Else
    17. gesEK = 0
    18. Catch ex As Exception
    19. MessageBox.Show("SUB: gesEK" & vbCrLf & vbCrLf & ex.Message)
    20. End Try
    21. con.Close()
    22. End Function
    23. End If
    Funktioniert Textverkettung durch ​+= eigentlich bei ​Option Strict On auch noch?
    Oder akzeptiert dies der Compiler als C#-Kompatibilität?

    Saubere Vorgehensweise bei VB:
    Mit ​+ addiert man Zahlen. Mit ​& verkettet man Strings.
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --