Avatar billede jademutter Nybegynder
07. august 2007 - 14:44 Der er 3 kommentarer og
1 løsning

Struktur problem?

Hej Eksperten

Jeg skal til at opbygge en database, men jeg har et lille problem som jeg ikke kan finde løsningen på.
Forretningslogikken er lidt svær at forklare, men jeg forsøger.

Jeg har et lager hvor det er muligt at tilføje/fjerne produkter.
Hvis der ikke er sket nogle ændringer skal beholdningen overføres til næste dag.
Den 6/8 er der 10 stk. på lager, der sker ingen bevægelser d. 7/8 og 8/8, men den 9/8 fjernes der 2 stk., altså:

6/8-2007  10 stk.
7/8-2007  10 stk.
8/8-2007  10 stk.
9/8-2007    8 stk.
10/8-2007  8 stk.

Problemet er at det ikke skal være nødvendigt at indtaste beholdning hver dag, med mindre der sker ændringer.

Hvordan opbygger jeg databasen, så jeg kan understøtte denne forretningslogik?

/Jademutter
Avatar billede nordclc Nybegynder
07. august 2007 - 15:10 #1
Normalt vil jeg sige, at man i en database ikke skal gemme ens records, dvs recorden d. 6-8/8 er ens bortset fra datoen. Du skal i stedet for kun gemme de datoer hvorpå der sker transkaktioner (tilgang/afgang fra lager). F.eks. vil du i dit tilfælde kun have følgende records i databasen:

6/8 10 stk
9/8 8 stk

Når du så skal finde beholdningen på en bestemt dato, kan du evt. benytte følgende sql:
select top 1 <beholdningsfelt> from <tabel> where <datofelt> <= #din_dato
Avatar billede jademutter Nybegynder
07. august 2007 - 17:27 #2
Mit problem er at jeg skal udregne leje på baggrund af den daglige beholdning.

sådan her:
6/8-2007  10 stk. gange 1 = 10 kr.
7/8-2007  10 stk. gange 1 = 10 kr.
8/8-2007  10 stk. gange 1 = 10 kr.
9/8-2007  8 stk. gange 1 =  8 kr.
10/8-2007  8 stk. gange 1 =  8 kr.

Samlet leje: 46 kr.

/Jademutter
Avatar billede kjulius Novice
07. august 2007 - 22:25 #3
Personligt ville jeg nok oprette en beholdningstabel og en transaktionstabel. Beholdningstabellen kunne enten indeholde den til enhver tid gældende lagerbeholdning eller en beholdning fra seneste status. For at få lagerbeholdningen på et givet tidspunkt ville man så skulle regne enten "forlæns" eller "baglæns". Der er fordele og ulemper ved begge metoder.

Hvis man tager udgangspunkt i en fast statusbeholdning skal den aktuelle beholdning altid udregnes hver gang den bruges. Til gengæld skal kun transaktionstabellen opdateres løbende.

Hvis man tager udgangspunkt i den til enhver tid gældende lagerbeholdning, skal både lagerbeholdnings- og transaktionstabellen opdateres hver gang der sker ændringer i lagerbeholdningen. Til gengæld er den aktuelle lagerbeholdning altid tilgængelig uden at skulle udregnes.

For begge gælder, at ALLE ændringer i lagerbeholdning skal udløse en transaktionsrecord i transaktionstabellen. Hver gang der plukkes fra lageret, hver gang der modtages og sættes varer på plads, hver gang der konstateres et svind (eller der findes en fejlplaceret vare og denne lægges på lager) skal der oprettes en transaktion. Det er den eneste måde man kan være sikker på, at kunne regne sig frem til den korrekte lagerbeholdning på et givet tidspunkt.




For versionen med en "statusbeholdning" vil en mulig tabel-konstruktion derfor kunne være:

Varebeskrivelse:
Id
Varenummer
Varebeskrivelse
Indkøbspris
Salgspris
Leverandør
Varetype

Statusbeholdning:
Id
VareId
Tidspunkt
Lagerbeholdning

Transaktioner:
Id
StatusId
Tidspunkt
Type
Lagerbevægelse



Den aktuelle lagerbeholdning kunne findes og vises ved at udføre noget lign. denne forespørgsel:

SELECT v.Varenummer, v.Varebeskrivelse, v.Salgspris, NZ(s.Lagerbeholdning, 0) + NZ(SUM(tr.Lagerbevægelse), 0) AS Lager
FROM Varebeskrivelse v
LEFT JOIN Statusbeholdning s ON s.VareId = v.Id
LEFT JOIN Transaktioner tr ON tr.StatusId = s.Id
WHERE v.Varenummer = 238
GROUP BY v.Varenummer, v.Varebeskrivelse, v.Salgspris

Den ønskede statistik (grundlag for regning) ville så kunne laves ca. sådan:

SELECT v.Varenummer, v.Varebeskrivelse, d.Dato, NZ(s.Lagerbeholdning, 0) + NZ(SUM(tr.Lagerbevægelse), 0) AS Lager, v.LejePrDag, NZ(s.Lagerbeholdning, 0) + NZ(SUM(tr.Lagerbevægelse), 0) * LejePrDag AS Dagsleje
FROM Varebeskrivelse v, Datoer d
LEFT JOIN Statusbeholdning s ON s.VareId = v.Id
LEFT JOIN Transaktioner tr ON tr.StatusId = s.Id
WHERE v.Varenummer = 238
  AND d.Dato BETWEEN #01/01/07# AND #01/31/07#
  AND tr.Tidspunkt < (SELECT MAX(Tidspunkt) FROM Transaktioner WHERE StatusId = s.Id AND Date(Tidspunkt) <= d.Dato)
GROUP BY v.Varenummer, v.Varebeskrivelse, d.Dato, v.LejePrDag


Bemærk, at vi her tilføjer en ekstra tabel, nemlig Datoer. Det er en såkaldt støttetabel, som bruges som omdrejningspunkt for statistikken. Den indeholder simpelthen alle datoer inden for den årrække, som programmet forventes at bruges:

Datoer:
Dato



(jeg har dog ikke på nogen måde testet ovenstående, så reelt er det ren teori, men du kan jo prøve det af... :-)
Avatar billede Slettet bruger
08. august 2007 - 08:49 #4
nordclc> husk DESC på dato eller brug LAST i stedet for!~)
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Dyk ned i databasernes verden på et af vores praksisnære Access-kurser

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester