Optellen

Status
Niet open voor verdere reacties.

benikke

Gebruiker
Lid geworden
9 apr 2023
Berichten
20
Dag allemaal,
Deze vraag gaat wel degelijk over Access.
Maar ik ga mijn bedoeling trachten uit te leggen in Excel.
Excel is een rekenprogramma daarvan ben ik me bewust.
En Access is een database (Die eenvoudige berekeningen aankan.)

Een tijd geleden maakte ik in Access eens een eenvoudige berekening.
Getal1 + getal2 is getal3 en daarna bij elke een nieuwe berekening

moest getal1 dezelfde waarde hebben als getal3 van vorige rij.

En dat wou maar niet lukken in Access.
Het is hier mogelijk niet helder uitgelegd daarom geef ik het voorbeeld in Excel.
[TABLE="class: MsoNormalTable, width: 232"]
[TR]
[TD="width: 77"][/TD]
[TD="width: 77"][/TD]
[TD="width: 77"][/TD]
[TD="width: 77"][/TD]
[/TR]
[TR]
[TD="width: 77"][/TD]
[TD="width: 77"]
[FONT=&amp]Getal1[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]Getal 2[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]Getal3[/FONT]
[/TD]
[/TR]
[TR]
[TD="width: 77"]
[FONT=&amp]Rij1[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]1[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]2[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]3[/FONT]
[/TD]
[/TR]
[TR]
[TD="width: 77"]
[FONT=&amp]Rij2[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]3[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]1[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]4[/FONT]
[/TD]
[/TR]
[TR]
[TD="width: 77"]
[FONT=&amp]Rij3[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]4[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]1[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]5[/FONT]
[/TD]
[/TR]
[TR]
[TD="width: 77"]
[FONT=&amp]Rij4[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]5[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]1[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]6[/FONT]
[/TD]
[/TR]
[TR]
[TD="width: 77"]
[FONT=&amp]Rij5[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]6[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]1[/FONT]
[/TD]
[TD="width: 77"]
[FONT=&amp]7[/FONT]
[/TD]
[/TR]
[/TABLE]

De kolom met getal3 is altijd het resultaat van deze kleine optelling.
De kolom met getal1 (bij een nieuwe optelling) is steeds weer een kopie van vorig getal3 van vorige rij vermeerderd met getal2.


Hopelijk is het enigszins duidelijk, want ik weet het niet beter uit te leggen.

Mijn vraag is nu kan dit ook in Access (in een query maar hoe dan?)

Alvast bedankt voor het antwoord.
 
Hallo, het grote verschil tussen een database en een rekenblad is dat de rijen (of lijnen, records, tuples of hoe je ze wil noemen) geen enkele volgorde hebben, tenzij de tabel een clustered index heeft, maar ik denk niet dat dit in Access kan of bestaat.
Een query vraagt de bestaande gegevens op en daar kan je de sorteervolgorde aangeven waarin de gegevens moeten weergegeven worden.

Wat jou voorbeeld betreft: je kan in Access een formulier maken waarin je zegt dat na het invullen/aanpassen van [Getal1] en [Getal2] , [getal3] = [Getal1] +[Getal2] en vervolgens de default waarde van het veld [Getal1] gelijk stellen aan [Getal3]. En zo kan je het raster via het formulier verder invullen. Maar geen idee wat je daarmee wil bereiken, en er is geen enkele garantie dat als je het formulier sluit en na een tijd terug opent het dezelfde gegevens in dezelfde volgorde toont.
 
Kijk eens in dit draadje, daar staat de oplossing. Inderdaad, gewoon meteen query. Vergeet de vorige oplossing :).
 
Dat kan zeker in Access, maar je legt het in ieder geval niet in deze vorm vast. Een kenmerk van een goed ontworpen tabel is dat je alleen de basisgegevens vastlegt en geen afleidbare of berekende gegevens.
Voor dit verhaal betekent dat dan dat je alleen de reeks getallen 1, 2, 1, 1, 1, 1 vastlegt en voor ieder getal de positie in de reeks.
Het weergeven van de gegevens is dan een ander verhaal. De kolommen 1 en 3 laten zich in een query berekenen (som van de vastgelegde getallen van de voorgaande rijen).
Merk in dit kader ook op jouw getal rij1/getal1 feitelijk een "getal2" is (getal uit de reeks), want geen som van.
 
Laatst bewerkt:
Ik snap de laatste opmerking van Peter niet, maar dat hoeft denk ik ook niet, want lijkt mij niet ter zake doende. Ik kan mij namelijk niet voorstellen dat deze getallen representatief zijn voor de werkelijke waarden in de tabel, en dat het wellicht om één of twee ingevoerde meetwaarden gaat die meeberekend moeten worden. Hoe dan ook: de oplossing staat al in bericht #3, dus het lijkt mij zinvol om die variant eerst te bekijken. Of iemand moet een betere hebben. Heb je mijn aandacht ook weer :d.
 
Ik denk niet dat dit meetresultaten zijn, maar gewoon een leuk rekenspelletje. Wat je nodig hebt is het startgetal (hier eerste lijn getal1 = 1) en dan een kolom met gegeven getallen (kolom2). De rest moet berekend worden. Getal 3 is eenvoudig in een query te berekenen als = getal 1 + getal2.
Het getal 1 voor de tweede en volgende lijnen wordt moeilijker omdat een dataset geen volgorde heeft. Daarom kan ik me vinden in het idee van Peter dat je een extra kolom toevoegt waarin je de gewenste sorteervolgorde zet. Dan kan je eventueel een query schrijven waarin je de datset linkt aan zichzelf op sorteervolgorde = sorteervolgorde -1. Zo zou je de somwaarde uit de vorige rij kunnen halen.
 
De getallen komen, lijkt mij, sowieso uit een tabel. Daar zet je heel eenvoudig een Autonummerveld in, en als jij het niet doet, doet Access het zelf wel. Dus de volgorde van de getallen ligt echt wel vast. Tenzij ik gekke Henkie ben, en TS dat tegenspreekt. (geldt ook voor het spelletjes idee. Een spellletje waarbij je steeds de waarde 1 optelt? Te moeilijk voor mij :)).

En dan verwijs ik voor de werkende oplossing van het probleem dus gewoon naar bericht #3. Dat helpers daar niet naar kijken snap ik, maar ik hoop toch weer een keer iets van TS te horen, dan kunnen we naar de volgende (help)stap.
 
Het probleem met een autonumber veld is dat je zelf de volgorde niet kan bepalen, dus ik zou zeggen: in sit geval best een gewoon integer veld
 
Mensen, even een verduidelijking. Ik ben een 75+ fossiel die zich onder andere bezig houd met Access als hersengymnastiek. Al jaren zit ik in een rolstoel en ben ik iemand die ook wel eens “wandelen” gaat met zijn schootmobiel.
Die schootmobiel moet ook worden opgeladen en dan was het fijn om mijn gereden kilometers te kennen.
Dus ziet mijn tabel er zo uit.
[TABLE="class: MsoNormalTable, width: 335"]
[TR]
[TD="width: 77"][/TD]
[TD="width: 137"][/TD]
[TD="width: 155"][/TD]
[TD="width: 77"][/TD]
[/TR]
[TR]
[TD="width: 77"][/TD]
[TD="width: 137"] [FONT=&quot]id[/FONT]
[/TD]
[TD="width: 155"] [FONT=&quot]AutuNummering[/FONT]
[/TD]
[TD="width: 77"][/TD]
[/TR]
[TR]
[TD="width: 77"][/TD]
[TD="width: 137"] [FONT=&quot]Vandaag is het[/FONT]
[/TD]
[TD="width: 155"] [FONT=&quot]Datum/tijd[/FONT]
[/TD]
[TD="width: 77"][/TD]
[/TR]
[TR]
[TD="width: 77"][/TD]
[TD="width: 137"] [FONT=&quot]Vorige tellerstand[/FONT]
[/TD]
[TD="width: 155"] [FONT=&quot]Numeriek[/FONT]
[/TD]
[TD="width: 77"][/TD]
[/TR]
[TR]
[TD="width: 77"][/TD]
[TD="width: 137"] [FONT=&quot]Tellerstand nu[/FONT]
[/TD]
[TD="width: 155"] [FONT=&quot]Numeriek[/FONT]
[/TD]
[TD="width: 77"][/TD]
[/TR]
[TR]
[TD="width: 77"][/TD]
[TD="width: 137"] [FONT=&quot]Opmerking[/FONT]
[/TD]
[TD="width: 155"] [FONT=&quot]Korte tekst[/FONT]
[/TD]
[TD="width: 77"][/TD]
[/TR]
[TR]
[TD="width: 77"][/TD]
[TD="width: 137"][/TD]
[TD="width: 155"][/TD]
[TD="width: 77"][/TD]
[/TR]
[/TABLE]
Daarvan is een query gemaakt en daarvan en formulier.
Uiteindelijk wil ik dat “[FONT=&quot]Vorige tellerstand” automatisch gekopieerd wordt naar [/FONT][FONT=&quot]Tellerstand nu”. Het van elkaar aftrekken van die twee geeft me in de query het aantal gereden kilometers.[/FONT]
De oplossing in bericht #3 is mogelijk ‘het van het’ maar het zegt me niets, omdat ik Access niet zo goed ken als jullie.
Het is dus een spelletje waarbij je steeds wat berekend.
In de hoop dat jullie met een concrete oplossing komen, zijn jullie alvast bedankt.
 
Wat ik niet begrijp is dat je in de eerste post komt met een lange uitleg en dan zegt dat je komt met een voorbeeld = bestand in Excel maar je komt met een 'plaatje'. Als ik de laatste post lees denk ik dat je het beter in Excel kunt zetten. Je zegt ook: 'waarbij je steeds wat berekend'. Daar is Excel voor.

"De oplossing in bericht #3 is mogelijk ‘het van het’ maar het zegt me niets, omdat ik Access niet zo goed ken als jullie" Dus dat blijft dan prutsen?

"In de hoop dat jullie met een concrete oplossing komen, zijn jullie alvast bedankt."
Jij bedoelt dan een oplossing die jij begrijpt en waar je mee kan werken?

Volgens mij krijg je hulp van zeer deskundige en ervaren helpers op dit gebied.

Denk toch eerder aan Excel.
 
“Volgens mij krijg je hulp van zeer deskundige en ervaren helpers op dit gebied.”
Vooreerst ben ik me bewust van jullie deskundigheid en hulp, waarvoor mijn dank.
“In de hoop dat jullie met een concrete oplossing komen, zijn jullie alvast bedankt.
Jij bedoelt dan een oplossing die jij begrijpt en waar je mee kan werken? “

Er kan inderdaad klakkeloos wat gekopieerd worden door mij en dat zal wel werken, maar ik wil ook nog graag begrijpen waarom dat zo is.
En betreffende Excel was dat voor mij een oplossing, maar mijn vraag was of dat ook in Access kon?
En uit respect voor het ganse team, zeg ik nogmaals bedankt.
 
Ik denk dat de meest eenvoudige oplossing dan is om bij het invoeren van een nieuwe regel hebben de vorige tellerstand automatisch te laten invullen als de tellerstand van de vorige datum. Dus dit in een formulier te laten oplossen. Dat kan volgens mij via een eenvoudige macro. Zelf werk ik niet zoveel meer met formulieren, maar daar kunnen een paar andere helpers je vast wel verder bij helpen.
 
Nu ik het achterliggende verhaal heb gelezen, is het ‘probleem’ eigenlijk niet bestaand, en is mijn oplossing uit bericht #3 gewoon de enige juiste oplossing. De ‘oplossing’ van Noëlle zorgt voor dataredundantie, en niet-gerelateerde gegevens, en dat moet je echt vermijden. Dat weet Noëlle overigens ook wel…

Op basis van de velden <RegistratieDatum> (gebruik geen spaties in veldnamen) en Tellerstand kun je namelijk alles berekenen en in een query/formulier laten zien. Het is volkomen onnodig om de vorige tellerstand op te slaan in een tabel, noch de gereden kilometers: beide gegevens zijn prima te berekenen in een query. Volgens mijn methode dus.

Nu dus het échte probleem: je snapt die oplossing niet. Dat kan, en dan komen we dus bij stap 2 aan (zie bericht #7): hoe bouwen dat bij jou in? Heel simpel: ik kan de gevraagde oplossing posten die in een voorbeeldje zit, in de hoop dat je die kan overnemen in jouw database. Of je post jóuw database mee, en ik bouw hem daar in. Ter lering ende Vermaeck :).

Laten we het probleem simpel houden, en post jouw database mee in een bericht (database eerst comprimeren en herstellen, en dan een zip bestand van maken) en dan kan een van de helpers dat zo inbouwen. En dan pas ik ook nog de tabel en het formulier voor je aan :).
 
En, omdat het toch regent, mijn voorbeeldje maar even aangepast aan de situatie van benikke. Zoals ik al eerder schreef: het is meer dan voldoende om alleen de datum in te vullen, en de actuele meterstand. De query berekent dan de rest. Dat kun je zien in het formulier dat opent met de bijgeleverde database; de onderliggende query bevat de noodzakelijke formules om die gegevens op te halen en te berekenen. Die query heeft echter wel een nadeel: hij is niet geschikt om gegevens in te voeren.

Dat is simpel op te lossen door op de tabel een apart invulformulier te maken waarin je de nieuwe tellerstand kunt invullen. Dat formulier kun je makkelijk openen middels een klik op een datum; daarmee start je een actie die vraagt of je een nieuwe tellerstand in wilt voeren. Als je dat gedaan hebt, wordt het lijstformulier ververst en zie je de nieuwe gegevens terug in het formulier.

E.e.a. wordt aangestuurd met een paar kleine VBA procedures. An sich allemaal niet nodig, want je kunt het invoerformulier altijd apart opstarten om een nieuwe tellerstand in te voeren, en het formulier met de berekeningen werkt ook prima zonder VBA; alles zit in de query tenslotte. Maar dankzij de code werkt het allemaal nét wat handiger. Zo zie je, als je vanuit het overzicht het invoerformulier opstart, ook de laatste tellerstand in de titel. Dat is wel zo handig, want je moet natuurlijk geen tellerstand invoeren die láger is dan de al ingevoerde waarden. Want dat is fysiek niet mogelijk. Overigens zijn er genoeg opties om dat ook dicht te timmeren, maar daar gaat de vraag nu niet over.
 

Bijlagen

Bedankt, dat je dit voor mij doet, ik ben volop bezig om uit te zoeken hoe die query opgebouwd is/werkt.
Ik weet niet goed hoe en wat ik terug kan doen. Maar je weet nooit hoe een koe een haas vangt. Alleszins erg bedankt.:thumb:
 
Ik weet niet goed hoe en wat ik terug kan doen.
Nou, dat lijkt mij nergens voor nodig :). De grap van een forum is dat mensen bereid zijn om hun kennis te delen, en eventueel met een voorbeeldje dat te onderstrepen. Aan jou dan de 'opdracht' om die kennis toe te passen in je eigen situatie. Eventueel kan ik de query nog wel voor je uitleggen/beschrijven zodat je het de volgende keer zelf kan.
 
Komt ie :). Ik gebruik wel een versie die een klein beetje anders is; de versie in de bijlage heeft nog een query waarbij de knop Totalen aan staat. Dat hoeft niet, die mag je dus uitzetten. De query doet dan precies hetzelfde. In de Ontwerpweergave ziet de query er zo uit:

Scootmobiel.png

De SQL die als basis fungeert voor de query (via de knop <Weergave> kun je de SQL weergave aanzetten) ziet er dan zo uit:

Code:
SELECT Registratiedatum, DatePart("ww",[Registratiedatum],2,2) AS Weeknummer,
     (SELECT TOP 1 Tellerstand FROM tblScootmobiel AS T1 WHERE T1.Tellerstand < tblScootmobiel.Tellerstand ORDER BY T1.Tellerstand DESC ) AS VorigeTellerstand, 
     Tellerstand, IIf([VorigeTellerstand] Is Null,0,[Tellerstand]-[VorigeTellerstand]) AS Verbruik, Tankbeurt
FROM tblScootmobiel
ORDER BY Registratiedatum;

Waar het om gaat, is dus deze regel:
Code:
(SELECT TOP 1 Tellerstand FROM tblScootmobiel AS T1 WHERE T1.Tellerstand < tblScootmobiel.Tellerstand ORDER BY T1.Tellerstand DESC ) AS VorigeTellerstand
Wat hier gebeurt, is eigenlijk heel simpel: er wordt een extra veld aangemaakt, waarbij de waarde wordt bepaald door een aparte query. Wij noemen dat dan een subquery. Dat mag, als die subquery aan één specifieke voorwaarde voldoet: de uitkomsd van die query mag, nee: móet altijd één waarde als uitkomst hebben. Je zou die subquery ook zelfstandig moeten kunnen draaien, en dan moet er dus ook één waarde uitkomen.
Normaal gesproken laat een query alle records zien, maar om af te dwingen dat je maar één record en één veld nodig hebt, begin je de query dan zo:
Code:
(SELECT TOP 1 Tellerstand

Daarmee ben je er natuurlijk nog niet, want je wilt een heel specifiek record hebben: de voorlaatste tellerstand van het laatste record in de tabel.

Er zit dus een voorwaarde aan die waarde die je wilt zien. En dat bereik je door een kopie te maken van de tabel waarin je werkt. Dat gebeurt hier:
Code:
(FROM tblScootmobiel AS T1
Die kopie mag elke naam hebben die je wilt, ik hou 'm zelf zo kort mogelijk voor de leesbaarheid.
Dan heb je dus een query gemaakt met in essentie twee identieke tabellen (de tabel T1 is immers een kopie van de tabel tblScootmobiel) en dat betekent dat je een criterium op die tabel kan maken.
Code:
WHERE T1.Tellerstand < tblScootmobiel.Tellerstand

Hierbij wil je dus alléén die waarden zien waarbij de Tellerstand uit tabel T1 kleiner is dan de tellerstand uit tblScootmobiel.

Voorlaatste record.png

Het laatste stukje is dan relatief simpel:
Code:
ORDER BY T1.Tellerstand DESC) AS VorigeTellerstand
Omdat je de voorlaatste meterstand wilt zien, moet er aflopend worden gesorteerd. Omdat meterstanden altijd oplopen, kun je dat dus doen door te sorteren op het veld Tellerstand, maar je kunt ook aflopend sorteren op een Datumveld, of een Autonummerveld. Als het maar een veld is waarvan je 100% zeker bent dat het altijd oplopend is in de tabel.

De complete subquery als zelfstandige query ziet er zo uit:
Code:
SELECT TOP 1 T1.Tellerstand FROM tblScootmobiel AS T1, tblScootmobielWHERE T1.Tellerstand<[tblScootmobiel].[Tellerstand]
ORDER BY T1.Tellerstand DESC;
En in de ontwerpweergave:

Subquery.png

Is een heel klein beetje anders, omdat de tabel tblScootmobiel er nog bij geplaatst moet worden. Wil je meer records zien, dan kun je voor de gein van Top 1 bijvoorbeeld Top 25 maken; dan zie je meer records (25 namelijk).

Subquery output.png

Hierbij valt hopelijk ook nog wat op, en dat heb ik even in een Excel spreadsheet gezet om met kleurtjes aan te geven: Het aantal records dat identiek is, neemt toe met het aantal gevonden waarden. Wat logisch is: als je naar de bovenste waarde kijkt, is er maar één record dat voldoet aan het criterium, Bij het tweede record zijn dat er al twee, bij het derde drie en zo verder. Omdat we alleen de bovenste willen hebben, zitten we met Top 1 dus helemaal goed :).

Wil je deze output geschoond in een query zien, dan moet je SELECTDISTINCTROW gebruiken i.p.v. TOP 1. Maar dat valt buiten de oorspronkelijke vraag :).

Ik hoop dat de uitleg e.e.a. zo wat duidelijker heeft gemaakt :). Er moet me nog wel iets van mijn hart: jouw hele vraag is bepaald geen beginnersvraag. Ik heb de indruk dat je nog een beginnende gebruiker bent, en dan moet je dit soort vragen eigenlijk nog niet stellen. Probeer eerst te begrijpen wat Access nu precies is, en vooral hoe een database opgezet moet worden, en wat de beginselen van normaliseren etc. zijn. Access is absoluut geen Click-And-Go programma zoals Word en Excel wellicht wél voor je zijn; je moet echt enige tijd steken in het leren begrijpen van in ieder geval de basisbeginselen van een database. Nu stel je een behoorlijk ingewikkelde vraag, en krijg je antwoorden die je niet snapt. Daar heb je, denk ik, dus eigenlijk ook niet zo veel aan :).
 
Het is inderdaad een hele kluif. Beschouw mij maar al beginner, alhoewel ik reeds een tijd met Acces (office 2013) bezig ben, maar bezie dat als bezig zijn met eenvoudige dingen. Dat word enkel gedaan als geheugen gymnastiek, en vandaar uit komen dan dingen voort die ik me afvraag. Maar ik ben heel blij dat dit "probleem" een goed einde kent. Veel dank daarvoor en wellicht tot een volgende keer, het ga je goed.:thumb:
 
Dan zien we de volgende vraag met genoegen tegemoet :).
 
Status
Niet open voor verdere reacties.
Terug
Bovenaan Onderaan