Query werkt niet goed.

Status
Niet open voor verdere reacties.

MrBurns

Gebruiker
Lid geworden
3 okt 2004
Berichten
28
Dag, ik heb ruzie met Access 2013.

Ik heb 1 grote tabel ("LEGO-onderdelen") in Access staan met alle LEGO-onderdelen die ik thuis heb. Deze tabel bestaat uit de volgende velden:

- ID (type Autonumber)
- LEGO-ID (type Short Text)
- Quantity (type Number)
- Color (type Short Text)
- Description (type Short Text)
- Location (type Short Text)
- Sub-location (type Short Text)
- Remarks (type Short Text)

Daarnaast heb ik een hele hoop kleinere tabellen met alle LEGO-sets die ik heb (1 tabel voor iedere set). Hierin staan de volgende velden:

- ID (type Autonumber)
- LEGO-ID (type Short Text)
- Quantity (type Number)
- Color (type Short Text)
- Description (type Short Text)

Als ik nu een LEGO-set "X" wil bouwen, dan gebruik ik een query die "LEGO-onderdelen" en "X" aan elkaar koppelt. De velden die identiek moeten zijn , zijn LEGO-ID en Color. Op die manier zie ik snel welke onderdelen ik nodig heb én in welke locatie ik die kan vinden.

Dat gaat bijna perfect. Het gaat alleen fout als een LEGO-onderdeel bijvoorbeeld het LEGO-ID 4265b heeft. Als het 4265 was geweest, was het goed gegaan maar doordat er een letter bij staat (b) verschijnt dat LEGO-onderdeel simpelweg niet in de resultaattabel. Ik heb uiteraard nagekeken of er tussen "X" en "LEGO-onderdelen" bij de betreffende velden iets verschillends staat, maar dat is niet het geval. In beide tabellen staat echt "4265b".

Heeft iemand enig idee waarom Access hier over struikelt?

(4265b was slechts een voorbeeld, het gebeurt met alle LEGO-IDs waar een letter bij staat)


UPDATE: En nu zijn uit de tabel "X" alle LEGO-ID velden waar ook een letter in stond, leeg (toen ik bovenstaande tekst schreef stond de betreffende data er nog wel). In de naastgelegen velden (Color enz.) staat alle tekst nog wel. Om de een of andere reden slaat Access op hol door de letters. Ik pruts nog even verder......

UPDATE 2: Ik heb 1 leeg veld in "X" opnieuw ingevuld (met 32064b, dus met een letter) en de query opnieuw gerund. Nu verschijnt het LEGO-ID wel in de resultaattabel. Ik zal dus alle lege velden opnieuw handmatig moeten invullen... blijft de vraag waarom Access dit gedaan heeft. Ik heb de data vanuit Excel in Access geplakt. Dat is het enige dat ik bedenken dat van invloed kan zijn geweest...
 
Laatst bewerkt:
Lijkt mij eerder dat Access 2013 ruzie heeft met jou.
En wel omdat je opzet totaal niet deugt.
Zo zou je, als je het netjes aanpakt in Access, al je sets in 1 tabelm moeten vastleggen.
En niet 1 tabel voor iedere set.

Misschien kun je een bijlage bijsluiten in Access 2007, dan kunnen we eens kijken hoe je eea wel netjes opzet.

Tardis
 
Nou... "totaal niet deugt" :confused:. Ik geloof graag dat het beter kan, maar helemaal hopeloos is mijn tot nu toe verrichtte handenarbeid nou ook weer niet. Tot nu toe was ik er erg blij mee :)

Maar goed, ik hoor graag hoe het beter kan (en wat de reden voor het originele probleem is). Ik ben aan het proberen om het bestand als bijlage toe te voegen (het is een Access 2013 bestand maar ik denk dat het ook werkt met 2007) maar ik krijg meldingen van een invalid file, dus ik moet even kijken wat er fout is.

Ik geloof dat het bestand gezipt moet worden, dus dat zal ik doen.

EDIT: Als ik het Access bestand zip dan is het ~300 kB maar zelfs dat is nog te groot...
 
Laatst bewerkt:
Je hebt legosets.
Die bestaan uit onderdelen.
Een bepaald onderdeel kan in meerdere sets voorkomen.

Dat betekent dat je uit gaat van 2 tabellen:

- tblSet; hier neem je alle sets in op
- tblOnderdeel; hier neem je alle onderdelen in op


Omdat een set meerdere onderdelen bevat en een onderdeel bij meerdere sets kan horen, heb je te maken met een zogenaamde veel-op-veel relatie.
Die moet je ombouwen naar 1-op-veel relaties.
Dat doe je door een tussentabel te maken, waarin je de primaire sleutels uit de 2 andere tabellen in opneemt.

Kortom, je tabellen en je tabelstructuur eerst even aanpassen.
Mocht dat niet lukken, geef een gil.

Tardis
 
OK, heldere uitleg. Ik ga er even naar kijken. Ik laat je waarschijnlijk morgen wel weten of het gelukt is. Bedankt tot zoverre.
 
Ik neem aan dat ik - voordat ik de Settabellen met elkaar append - in iedere afzonderlijk settabel een veld moet toevoegen met de betreffende setnaam achter ieder onderdeel dat in die set voorkomt, toch (lekker duidelijke zin:))? Anders is het in de totale tabel niet meer duidelijk welke sets welke onderdelen bevatten...

Nu ik het zo opschrijf klinkt het wel erg logisch, maar ik denk toch maar even navragen.
 
Weet niet wat je met settabellen bedoelt.
Bedoel je daarmee je oorspronkelijke opzet, voor iedere set een aparte tabel?

Tardis
 
Ja. Iedere set heeft nu nog z'n eigen tabel (een settabel) met de volgende velden:

- ID (type Autonumber)
- LEGO-ID (type Short Text)
- Quantity (type Number)
- Color (type Short Text)
- Description (type Short Text)

Als ik nu 2 van deze tabellen samen voeg zie ik niet meer welke onderdelen bij welke set horen. Dus moet ik vóór het samenvoegen in iedere set-tabel achter ieder onderdeel de naam van de betreffende set zetten. Toch?
 
Ik heb even naar je tabellen gekeken, en behalve dat je structuur inderdaad nogal onhandig is zo met die losse tabellen, zit daar ook nog redudantie in die je niet wilt. Zo heb je in al die settabellen velden [Color] en [Description] zitten die ook al in Lego onderdelen zitten. Die velden kunnen er dus zowiezo uit. Dat je met Engelstalige veldnamen werkt is in deze situatie ook niet erg handig, want het veld [Quantity] in de settabellen is iets anders ([Aantal nodig] vermoed ik) als het veld [Quantity] in [Legovoorraad] (waarom die dan niet in het Engels?) waar het waarschijnlijk [Voorraad] betekent. Maar goed, dat maakt voor de werking natuurlijk niet uit. Je zou inderdaad, zoals al eerder gesuggereerd, één tabel moeten hebben voor je sets, waarin je deze velden zou moeten hebben:
tblSets
- ID (type Autonumber)
- Set nummer
- LEGO-ID (type Short Text)
- Aantal (type Number)
Om die tabel te vullen vanuit je bestaande tabellen is niet zo heel lastig, omdat je (vermoed ik) de setnamen gebruikt als tabelnaam. Met een simpele functie kun je daarom een Toevoegquery maken, waarbij je alle tabellen doorloopt, en alle velden gebruikt in een toevoegquery + de tabelnaam. Dan ben je in één keer klaar.
En daarna zo snel mogelijk die tabellen weggooien :)
 
Hoi Michel, klinkt allemaal goed. Zeker dat punt van redundantie is geloof ik nogal een beginnersfout die snel gemaakt is. Zal is kijken of ik het ook nog werkend kan krijgen :)

Heb je ondertussen enig idee waarom het probleem waarmee ik dit onderwerp begon, optrad?
 
Geen idee, maar dat boeit nu ook eigenlijk niet, omdat je structuur dus niet klopt. Ik zal het niet zo sterk zeggen, maar het is een feit dat het niet klopt. Overigens vermoed ik dat Tardis een beetje last heeft gehad van een zonnesteek toen hij dit schreef:
Omdat een set meerdere onderdelen bevat en een onderdeel bevat en een onderdeel bij meerdere sets kan horen, heb je te maken met een zogenaamde veel-op-veel relatie.
Mij lijkt het eerder dat een set uit een aantal onderdelen bestaat, waarvan je in de set het aantal aangeeft; één onderdeel wordt dus in één set maar één keer opgenomen. Uiteraard kan een onderdeel in meerdere sets gebruikt worden. Ergo: je hebt gewoon een één-op-veel relatie tussen Sets en Onderdelen.
Ik heb ondertussen een functie gemaakt die in één keer de tabel tblSets vult met de juiste gegevens. Op basis van jouw voorbeeldje doet hij er ongeveer 0,123 seconde over, dus wellicht is overtypen sneller :)
Code:
Sub SetsVullen()
Dim strSQL As String
Dim obj As AccessObject, dbs As Object
    Set dbs = Application.CurrentData
    For Each obj In dbs.AllTables
        If IsNumeric(obj.Name) Then
            strSQL = "INSERT INTO tblSets ( LegoID, Aantal, SetID ) " _
                & "SELECT LegoID, Quantity, " & obj.Name & " AS Expr1 " _
                & "FROM " & obj.Name
            CurrentDb.Execute strSQL, dbFailOnError
        End If
    Next obj
End Sub
De code plak je in een nieuwe (of bestaande) module, en kun je gelijk uitvoeren. Maar één keer doen, anders vult hij de tabel meer dan 1 keer, en dat wil je uiteraard niet. Kun je voorkomen door een index te maken van [LegoID] en [SetID] omdat dus in mijn ogen dat een unieke combinatie is.
 
Ik heb je tabellen nog eens bestudeerd, en geconstateerd dat er nog een kleine lacune in zit, en dat is dat je eigenlijk in Sets het OnderdeelID moet opslaan, en niet het LegoID. Waar dat nummer vandaan komt weet ik niet, al vermoed ik dat dit een artikelcategorisatie is waar nog een subverdeling in kleur etc onder zit. Een set bestaat echter wel degelijk uit een artikel uit je Onderdelenlijst, dus je wilt dat OnderdeelID opslaan, en niet het LegoID. Maar je moet wel matchen op LegoID en kleur. Ik vermoed ook dat je daarom die extra velden in de set tabellen had staan. Zoals gezegd: die moeten er dus uit, want die veroorzaken dataredundantie.
De vernieuwde functie ziet er nu dus zo uit:
Code:
Sub SetsVullen()
Dim strSQL As String
Dim obj As AccessObject, dbs As Object
    Set dbs = Application.CurrentData
    For Each obj In dbs.AllTables
        If IsNumeric(obj.Name) Then
            strSQL = "INSERT INTO tblSets ( Aantal, SetID, Onderdeel_ID ) " _
                & "SELECT Quantity, " & obj.Name & " AS Expr1, tblOnderdelen.OnderdeelID " _
                & "FROM " & obj.Name & " INNER JOIN tblOnderdelen ON ([" & obj.Name & "].Description = tblOnderdelen.Omschrijving)  " _
                & "AND ([" & obj.Name & "].Color = tblOnderdelen.Kleur) AND ([" & obj.Name & "].LegoID = tblOnderdelen.Lego_ID);"
            CurrentDb.Execute strSQL, dbFailOnError
        End If
    Next obj
End Sub
Belangrijkste verschil is, dat je nu het OnderdeelID ophaalt uit tblOnderdelen, en dat doe je door de velden [Description], [Color] en [LegoID] te matchen. De query doet er nu 0,125 seconde over :)
 
Ik ga hier straks even op mijn gemak naar kijken Michel, maar ik begrijp zo snel niet wat je met OnderdeelID bedoelt. Bedoel je het eerste veld dat ik in de settabellen heb staan? Want dat is een ID dat ik er door Access in heb laten zetten en wat dienst doet als primaire sleutel. De LEGO-IDs geven het soort onderdeel aan, en 1 LEGO-ID kan in meerdere kleuren voorkomen.

Ps. De 2e query doet er 0,02 seconden langer over. Het is maar goed dat dit vrijetijdsbesteding is, want als het werkgerelateerd was geweest had ik het niet kunnen verkopen aan de baas :D
 
Ik heb dat veld inderdaad omgedoopt naar OnderdeelID. Ik vind dat je velden herkenbaar moet benoemen :)
 
Overigens vermoed ik dat Tardis een beetje last heeft gehad van een zonnesteek toen hij dit schreef

Goed bezig, bedankt dat je we er weer eens op wijs dat je het allemaal zo ******* goed weet.
Tja aan jou kan ik niet tippen, ben er weer vantussen.

Tardis
 
En neem dan gelijk je gevoel voor humor mee terug naar de winkel, met een beetje mazzel heb je het bonnetje nog en kun je het nog ruilen. Dit

En wel omdat je opzet totaal niet deugt.
Was ook al niet de meest vrolijke opmerking van de dag... Dus jij lijkt mij niet de meest aangewezen persoon om op een 'moral high horse' te gaan zitten.
 
Laatst bewerkt:
Hmm... ik heb de eerste functie uitgevoerd en dat ging goed, maar als ik de 2e functie probeer te draaien zegt hij "The specified field "Quantity" could refer to more than one table listed in the FROM clause of your SQL statement."

Huh...? Wa...?
 
Als veldnamen hetzelfde zijn in twee tabellen, krijg je dat probleem. Dan moet je ofwel de veldnaam in een van de tabellen veranderen, ofwel de naam van de tabel opnemen in de query, zodat Access weet uit welke tabel het veld gehaald moet worden. In de SQL vind je daar al voorbeelden van.
 
Sorry, een paar stappen terug want ik snap er niks meer van. De bedoeling van de eerste functie was om een totaaltabel van alle sets te maken. Duidelijk.

Wat is de bedoeling van de 2e functie?
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan