21. září bude sraz! Od 18.00 v restauraci Tradice v Praze u Anděla
Autor Zpráva
Michales
Profil
Dobrý den, už několikrát mi zde bylo vyktnutý špatný návrh databáze.

Takže bych chtěl poprosit o radu jak by měla databáze vypadat.
Do databáze se bude ukládat toto csv https://docs.google.com/spreadsheets/d/1JhaC31BTshYf5CptXREb6r0oRH4qbI9JDT_IWOhV3BA/edit?usp=sharing případně ke stažení https://drive.google.com/file/d/0B0P0rFdHdMc_ZVZ1MVVlTnhIMlU/view?usp=sharing

Jedná se o databázi hudby. Každý interpret má své CSV, interpret je uveden ve sloupci Contentgroup.
Osobně mě napadá dělat pro každého interpreta vlastní tabulku, ale nyní je jich zhruba 400 což se mi nezdá jako dobrý nápad.

Jako další mě napadá udělat 3 tabulky.
1. tabulka např. Interpreti
Do té by se uložil zmiňovaný sloupec Contentgroup + ID
2.tabulka např. Alba
Do té by se ukládali názvy alb sloupec Album + ID.
Tohle jsou řádky které se zbytečně opakuji.
A pak 3. tabulku kam by se uložil ten zbytek + příslušné ID z těch dvou tabulek.

Měli by jste někdo nějaký návrh jak datábázi stvořit?
Díky
-----------------------------
PS: Momentálně to teď vše nahrávám do jedné tabulky. Což je špatně
Kajman
Profil
Jednoduchý příklad se třemi tabulkami je v online demu na http://www.adminer.org/
Komplikací budou alba od více interpretů (výběry písniček).

A obecně se při návrhu tabulek přiklánějte k normalizaci.
Michales
Profil
Kajman:
Žádné výběry nejsou. Vždy jen Jen jedno jméno a v jednom CSV.
Pokud už o nějaký výběr jde tak má v Contentgroupu Various Artist.
A co s tím příkladem? Nějak jsem to nepochopil.
Otázkou bylo jak navrhnout správně databázi.
Kajman
Profil
Je tam příklad navržení databáze téměř toho stejného.

1. tabulka interprets - údaje umělců
2. tabulka albums - údaje alba + provázání s interpretem
3. tabulka songs - údaje písničky + provázání skladby s albem

CREATE TABLE `interprets` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(50) NOT NULL COMMENT 'Name',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Interprets';

CREATE TABLE `albums` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `interpret` int(11) NOT NULL COMMENT 'Interpret',
  `title` varchar(100) NOT NULL COMMENT 'Title',
  PRIMARY KEY (`id`),
  KEY `interpret` (`interpret`),
  CONSTRAINT `albums_ibfk_1` FOREIGN KEY (`interpret`) REFERENCES `interprets` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Albums';

CREATE TABLE `songs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `album` int(11) NOT NULL COMMENT 'Album',
  `rank` tinyint(4) NOT NULL COMMENT 'Rank',
  `title` varchar(100) NOT NULL COMMENT 'Title',
  `duration` time NOT NULL COMMENT 'Duration',
  PRIMARY KEY (`id`),
  KEY `album` (`album`),
  CONSTRAINT `songs_ibfk_1` FOREIGN KEY (`album`) REFERENCES `albums` (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='Songs';
Michales
Profil
Kajman:
Děkuji za vysvětlení.
Ještě mi jde o to spíš jestli je tento návrh opravdu pro toto Csv dobré. Ale řekl by že asi ano.
juriad
Profil
Ukázka: adminer.sourceforge.net/adminer.php?username=&db=a264133_jmi8e235&select=interprets
Snaž se neuvažovat v databázových strukturách, ale ohledně toho, co k čemu patří. A kolik čeho může být.
Na první pohled je vidět:
Interpret má název

Album má název
Album má umělce (může být různé od interpreta)
Album má rok vydání
Album má vydavatele
Album má web
Album má heslo
Album má text
Album patří interpretovi

Písnička má název
Písnička má pořadí
Písnička má délku
Písnička má umělce (může být různé od interpreta i od umělce alba)
Písnička má skladatele
Písnička patří do alba

Nepřemýšlej, zda databáze odpovídá CSV; udělej databázi správně a pak do ní to CSV nalij jakýmkoli způsobem.
Michales
Profil
juriad:
Děkuji.
Tohle vypadá dobře.
Musím se nad tím zamyslet. Samotné zobrazení potom by neměl být problém. Spíš mě teď napadlo že vůbec nevím jakým způsobem to z toho csv dostat pak do těch tabulek. Ikdyž něco přeci. Udělat pomocnou tabulku kam bych nahrál scriptem csv tak jak je a následně to scriptem rozdělil do správných tabulek a pak tu pomocnou vyprázdnil.
Michales
Profil
Tak databázi jsem vytvořil podle juriad.
Nyní se snažím ty data z CSV dostat do těch tabulek. Je má úvaha v [#7] správná? Nebo to řešit nějak jinak?
juriad
Profil
Ano, lze to tak dělat.
Do jedné velké tabulky a následně data pomocí INSERT INTO tabulka SELECT DISTINCT sloupecky, ... FROM velka přesypeš.
Ještě se rozmysli, zda nechceš jednotlivým záznamům přidělit umělá ID (čísla) tak, jak navrhuje Kajman na 2., 8. a 17. řádku. Silně to doporučuji, ale pak se to zkomplikuje a nepůjde to tak snadno.

Ideální je však napsat si skript v PHP, který ta data z CSV do databáze vloží. Když si to rozmyslíš, není to o moc víc práce, a navíc ten skript můžeš upravovat, dokud nebudeš spokojený s vysledkem.
Michales
Profil
juriad:
To jsem podle Kajman udělal.

Ideální je však napsat si skript v PHP, který ta data z CSV do databáze vloží. Když si to rozmyslíš, není to o moc víc práce, a navíc ten skript můžeš upravovat, dokud nebudeš spokojený s vysledkem.

Myslíš tím že by ten script přímo to CSV rozebral a poslal do správných tabulek, bez použítí té pomocné tabulky?
Bylo by to úplně super, ale mé znalosti nejsou takové abych něco podobného napsal.
juriad
Profil
Koukám, že text se týká písničky, nikoli alba.
Něco jsem zkusil vytvořit; umí to do databáze nahrát libovolné CSV, které obsahuje záznamy hierarchického charakteru.
Toto mi funguje u databáze se strukturou podobnou té tvé; v polích cols jsou uvedeny sloupečky, které by databáze měla mít a v types je jejich typ.
gist.github.com/juriad/3287910cabc1d947c283
juriad
Profil
CREATE TABLE `interprets` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `albums` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `interpret` varchar(255) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `year` int(11) DEFAULT NULL,
  `albumartist` varchar(255) DEFAULT NULL,
  `publisher` varchar(255) DEFAULT NULL,
  `web` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

CREATE TABLE `songs` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `album` int(11) DEFAULT NULL,
  `name` varchar(255) DEFAULT NULL,
  `track` int(11) DEFAULT NULL,
  `artist` varchar(255) DEFAULT NULL,
  `composer` varchar(255) DEFAULT NULL,
  `length` int(11) DEFAULT NULL,
  `lyrics` int(11) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Na constrainty (FOREIGN KEY a NOT NULL) jsem neměl čas; doplň si je podle Kajmana a svého úsudku.
Alphard
Profil
Než sem dal juriad své řešení, připravoval jsem jednoduchou ukázku základní myšlenky. Její značnou výhodou pro pochopení je, že se vejde na 16 řádků, určitou nevýhodou je, že není kompletně funkční, jen ukazuje princip.

$filename = 'C:\web\www\tests\data\albums.csv';
$albums = [];
if (($handle = fopen($filename, 'r')) !== FALSE) {
    fgetcsv($handle, 1000, "*"); // skip first
    while (($data = fgetcsv($handle, 1000, "*")) !== FALSE) {
        $album = $data[1];
        $song = $data[4];
        if (false === ($key = array_search($album, $albums))) {
            $albums[] = $album;
            $key = count($albums)-1;
            echo sprintf('insert into albums (id, name) values (%d, %s)', $key+1, $album), PHP_EOL;
        }
        echo sprintf('insert into songs (id_album, name) values (%d, %s)', $key+1, $song), PHP_EOL;
    }
    fclose($handle);
}

Výstup:
insert into albums (id, name) values (1, Ernest Tubb Favorites)
insert into songs (id_album, name) values (1, Walkin' The Floor Over You)
insert into songs (id_album, name) values (1, I'll Always Be Glad To Take You Back)
...
insert into albums (id, name) values (2, Jimmie Rodgers Songs)
insert into songs (id_album, name) values (2, Mother, The Queen Of My Heart)
...
insert into albums (id, name) values (3, Old Rugged Cross)
insert into songs (id_album, name) values (3, The Old Rugged Cross)
insert into songs (id_album, name) values (3, Farther Along)
...
insert into albums (id, name) values (4, Red And Ernie)
insert into songs (id_album, name) values (4, Tennessee Border)
insert into songs (id_album, name) values (4, Goodnight Irene)
...
Michales
Profil
juriad:
Ahoj,

jsem velice potěšen tím že mi chceš pomoct.
Mám několik otázek.
Koukal jsem do toho scriptu a vůbec tomu nerozumím.
To CSV nevím jak tím prohnat.
Nevím jestli vložit do formulářového prvku a pak odeslat na tento script nebo jak?
Dále bych měl ještě prosbu,
Pokud budeš mít čas a chuť, je možné to upravit, bylo by to z důvodu toho že se po čase mohou alba doplňovat již k existujícímu interpretovi.
Tím pádem by se neměl už znovu zapisovat do tabulky interprets

Moc děkuji
------------------------

Tak už jsem zjistil že ten soubor musí být na ftp a musí se jmenovat songs.csv
juriad
Profil
Michales:
Zkusím to upravit, aby šlo inkrementálně přidávat záznamy. (Aby se k existujícím přidaly nové.)
Zatím je to kolekce funkcí, přičemž stačí zavolat tu hlavní (importCSV) a předat jí všechny argumenty.
Neměl by být problém to zakomponovat do existující aplikace (akce při odeslání formuláře).
Hezké by také bylo rovnou vytvářet tabulky podle schématu.

Myslím, že by se to mohlo hodit i dalším lidem; až budu mít čas (určitě ne tento týden; možná až o prázdninách) rozšířím to, doplním dokumentaci a vystavím jako projekt na GitHub.
Zatím však nemám čas cokoli s tím dělat. Včera jsem potřeboval změnit aktivitu, tak jsem si zaprogramoval.
Michales
Profil
juriad:
Letí k tobě velké dík, ať už za ochotu tak i za tvůj čas.
Moc děkuji.
Michales
Profil
Zde přikládám mé dočasné řešení:
Load CSV
Michales
Profil
juriad:
Zkusím to upravit, aby šlo inkrementálně přidávat záznamy. (Aby se k existujícím přidaly nové.)
Zatím je to kolekce funkcí, přičemž stačí zavolat tu hlavní (importCSV) a předat jí všechny argumenty.
Neměl by být problém to zakomponovat do existující aplikace (akce při odeslání formuláře).
Hezké by také bylo rovnou vytvářet tabulky podle schématu.
>
Myslím, že by se to mohlo hodit i dalším lidem; až budu mít čas (určitě ne tento týden; možná až o prázdninách) rozšířím to, doplním dokumentaci a vystavím jako projekt na GitHub.
Zatím však nemám čas cokoli s tím dělat. Včera jsem potřeboval změnit aktivitu, tak jsem si zaprogramoval.


Ahoj, připomínám se s dotazem jestli je tvá nabídka stále aktuální.
Díky za odpověď.

Vaše odpověď

Mohlo by se hodit

Odkud se sem odkazuje


Prosím používejte diakritiku a interpunkci.

Ochrana proti spamu. Napište prosím číslo dvě-sta čtyřicet-sedm:

0