ugrás a tartalomhoz

Adatbázis felépítése projektek kezelésére

ettemlevest · 2014. Már. 18. (K), 13.16
Sziasztok!

Olyan adatbázist szeretnék készíteni, amelyben projekteket és azokhoz rendelt különböző tulajdonságú erőforrásokat tudok tárolni. Nem tudom mi lenne az ideális megvalósítás, ebben kérem a segítségeteket.
A probléma, hogy egy-egy projekthez lehet rendelni anyagokat (mennyiség, költség), dolgozókat (2 fajta ledolgozott munkaórával, költséggel) és munkagépeket (szintén teljesített munkaórával és költséggel) valamint egyéb erőforrás (leírás, költség).

Én két adatbázisban kezdtem el gondolkodni. Projektek, ebben lennének az alapadatok:

CREATE TABLE IF NOT EXISTS `projektek` (
  `azonosito` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `projekt_megbizo_id` bigint(20) unsigned NOT NULL,
  `projekt_megnevezes` varchar(50) NOT NULL,
  `projekt_kezdes` date NOT NULL,
  `projekt_befejezes` date NOT NULL,
  `projekt_tervezett_koltseg` int(10) unsigned NOT NULL,
  `projekt_megjegyzes` varchar(255) NOT NULL,
  `felveve` datetime NOT NULL,
  `felvevo` varchar(50) NOT NULL,
  `modositva` datetime NOT NULL,
  `modosito` varchar(50) NOT NULL,
  `lezarva` datetime NOT NULL,
  `lezaro` varchar(50) NOT NULL,
  PRIMARY KEY (`azonosito`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Valamint a projektekhez rendelt erőforrások (az erőforrások adatait külön táblákban tárolom):

CREATE TABLE IF NOT EXISTS `projektek_naplo` (
  `azonosito` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `projekt_id` bigint(20) unsigned NOT NULL,
  `datum` date NOT NULL,
  `anyag_id` bigint(20) unsigned NOT NULL,
  `dolgozo_id` bigint(20) unsigned NOT NULL,
  `munkagep_id` bigint(20) unsigned NOT NULL,
  `mennyiseg` int(10) unsigned NOT NULL,
  `munkaora` int(10) unsigned NOT NULL,
  `kiemelt_munkaora` int(10) unsigned NOT NULL,
  `koltseg` int(10) unsigned NOT NULL,
  `felveve` datetime NOT NULL,
  `felvevo` varchar(50) NOT NULL,
  `modositva` datetime NOT NULL,
  `modosito` varchar(50) NOT NULL,
  `megjegyzes` varchar(255) NOT NULL,
  PRIMARY KEY (`azonosito`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
A problémám, hogy attól függően, hogy egy adott bejegyzés mondjuk anyag, akkor több oszlop teljesen felesleges (pl. dolgozo_id, munkagep_id, munkaora, kiemelt_munkaora). A másik, nagyobb problémám, hogy ilyen tárolás mellett a projekthez erőforrás hozzáadása, módosítása nem valami gördülékeny (külön kell vennem őket erőforrásonként). Gondolkodtam azon is, hogy szétszedem külön táblákra (pl. projektek_anyagok, projektek_dolgozok...).
Azonban az adatok megjelenítése egy táblázatban kellene, hogy legyen. Egy táblázat a projektek alapadatainak, a mellette egy másik táblázatban a kiválasztott projekthez rendelt 'dolgok' listája.

Remélem valamennyire érthetően tudtam megfogalmazni a problémámat. Ha valami nem pontos, megpróbálom javítani. Előre is köszönök minden segítséget.
 
1

Egy kérdés

Vilmos · 2014. Már. 18. (K), 15.30
Az erőforrások (gépek-anyagok-dolgozók) más-más adatokat tartalmaznak, kezelésükre külön szabályok vonatkoznak?
Ha nem egyformák, külön táblát érdemelnek, a karbantartásuk sem mehet egy kaptafára. Ha egyformák akkor "típuskódban" térnek el, ami emberi olvasatban merőben más, gépi feldolgozáskor mindegy, mert azonos mérőszámok vannak, óra, költség ...
2

Mindhárom típushoz tartozó

ettemlevest · 2014. Már. 18. (K), 16.11
Mindhárom típushoz tartozó adatok: projekt_id, datum, koltseg (ez dinamikusan van számolva), felveve, felvevo, modositva, modosito, megjegyzes. Az anyag_id, dolgozo_id, munkagep_id oszlopok adják meg, hogy mihez tartozik a bejegyzés.
Anyag saját adata: mennyiseg.
Dolgozó: munkaora, kiemelt_munkaora.
Munkagép: munkaora.

Az a probléma, hogy a dolgozóknak két fajta munkaórája lehetséges (a munkadíj miatt: normál, kiemelt). Ha csak egy lenne, akkor maradna egy mennyiseg oszlopom és könnyebb lenne minden :)
3

A naplónak nem kell

Vilmos · 2014. Már. 18. (K), 16.34
A naplónak nem kell feltétlenül olyannak lennie mint a kívánt kimenetnek. Az adatbázis tervezés az ilyesmit egy szóval elintézi: "nézet orientált tervezés". Lehetőség szerint kerülendő, gondolom több hátránya van mint előnye.

A költség tényezőkben van egy nem látható adattípus, a mennyiségi egység. A mennyiségi egységek alighanem típus függőek:

- anyag - sejthetően többféle, például darab
- dolgozó - eddig kétféle, normál munkaóra és kiemelt munkaóra
- munkagép - gépi munkaóra

Ha van ilyen mező, akkor nincs szükség külön oszlopra a munkaórák esetén.
4

Jelenleg erre jutottam

ettemlevest · 2014. Már. 19. (Sze), 08.57
Át lett gondolva egy kicsit a felépítés:

CREATE TABLE IF NOT EXISTS `projektek_naplo` (
  `azonosito` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `projekt_id` bigint(20) unsigned NOT NULL,
  `tipus` tinyint(4) unsigned NOT NULL,
  `datum` date NOT NULL,
  `anyag_id` bigint(20) unsigned NOT NULL,
  `dolgozo_id` bigint(20) unsigned NOT NULL,
  `munkagep_id` bigint(20) unsigned NOT NULL,
  `mennyiseg_1` int(10) unsigned NOT NULL,
  `mennyiseg_2` int(10) unsigned NOT NULL,
  `koltseg` int(10) unsigned NOT NULL,
  `felveve` datetime NOT NULL,
  `felvevo` varchar(50) NOT NULL,
  `modositva` datetime NOT NULL,
  `modosito` varchar(50) NOT NULL,
  `megjegyzes` varchar(255) NOT NULL,
  PRIMARY KEY (`azonosito`)
) ENGINE=MyISAM  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;
Letárolom, hogy milyen típusú a bejegyzés (anyag, dolgozó, munkagép, egyéb...) és ennek fényében jelenítem meg, dolgozom fel a mennyiségeket. A két mennyiség oszlopra a dolgozók két fajta munkaórája miatt van szükség, a többi típusnál nem lenne használva.

Eddig így kérdeztem le az adatokat:

SELECT projektek_naplo.*,
       anyagok.anyag_megnevezes,
       dolgozok.dolgozo_nev,
       munkagepek.munkagep_gyarto, munkagepek.munkagep_tipus, munkagepek.munkagep_azonosito
FROM $table
  LEFT JOIN anyagok ON projektek_naplo.anyag_id = anyagok.azonosito
  LEFT JOIN dolgozok ON projektek_naplo.dolgozo_id = dolgozok.azonosito
  LEFT JOIN munkagepek ON projektek_naplo.munkagep_id = munkagepek.azonosito
WHERE projekt_id = '$aktiv'
ORDER BY projektek_naplo.datum DESC
Ez így megfelelő-e vagy pazarló a select? Van-e ennél optimálisabb lekérdezés?
5

Félig off

Hidvégi Gábor · 2014. Már. 19. (Sze), 09.47
Talán manapság már annyira nem számít, de én szeretem az adatbázismezők tárhelyméretét a legkisebbre venni, ennyivel is gyorsabb lehet a feldolgozás.

A BIGINT(20) egy irdatlan nagy szám, mi általában INT-et (INT(11))-et használunk, ez is nagyjából kétmilliárd rekordot jelent, ami nem kevés.

Ha a későbbiekben tervezed, hogy más adatbáziskezelőket is kipróbálsz, akkor érdemes az SQL szabványhoz minél inkább illeszkedő táblákat és lekérdezéseket készíteni, amiben sajnos a MySQL nem jeleskedik:

1, ne használj "unsigned" típust
2, dátumok alapértelmezett értéke legyen NULL, mert a MySQL-féle '0000-00-00' gondot fog okozni