« 1 2 »
Autor Zpráva
tomas2245
Profil
Zdravím, rozhodol som sa že svoju tabuľku s objednávkami ktorá obsahuje 45+- stĺpcov rozdelím na 3 tabuľky: zakaznici, objednavky, objednavky_tovar

posielam obrázok ako si predstavujem ich štruktúru a neviem si dať rady s zakaznik_id, tovar_id a objednavky_id stačí toto jedno s funkciou AUTO INCREMENT? na spájanie tabuliek..

juriad
Profil
Tabulky mezi sebou musí mít vazby (což je vlastně sloupec ID z jiné tabulky).
Není to úplně špatně, ale ne vše má být VARCHAR (čas, cena)
Množství tabulek se neboj, na JOINy si rychle zvykneš.

Já bych to navrhnul takto:
# možná už tuto (podobnou) tabulku máš?
CREATE TABLE tovary (
  id INT PRIMARY KEY AUTO_INCREMENT,
  cena INT NOT NULL, # *
  popis TEXT NOT NULL # nějaký dlouhý popis
);

CREATE TABLE zakaznici (
  id INT PRIMARY KEY AUTO_INCREMENT,
  meno VARCHAR(255) NOT NULL,
  prizvisko VARCHAR(255) NOT NULL,
  email VARCHAR(255) NOT NULL, # email je povinný
  telefon VARCHAR(255) # telefon není povinný (telefon není číslo)
);

# adresu bych vyčlenil mimo, zákazník jich může používat víc
# adresu není možné měnit, jen je možné vytvořit novou, protože je použitá v objednávce
CREATE TABLE adresy (
  id INT PRIMARY KEY AUTO_INCREMENT,
  zakaznik_id INT NOT NULL,
  ulice VARCHAR(255) NOT NULL,
  mesto VARCHAR(255) NOT NULL,
  psc CHAR(5) NOT NULL # 5 znaků bude vždy stačit
);

# * pokud ti na cenu stačí celé číslo, tak INT,
#   jinak všechny ceny ukládej v centech a INT postačí také,
#   pak bys při výpisu vydělil cenu 100

CREATE TABLE objednavky (
  id INT PRIMARY KEY AUTO_INCREMENT,
  zakaznik_id INT NOT NULL,
  adresa_id INT NOT NULL,
  vytvorena DATETIME NOT NULL, # nikoli VARCHAR ani INT
  stav VARCHAR(255) NOT NULL, # často stačí i INT
  cena_celkem INT NOT NULL, # *
  poznamka TEXT # není povinná
);

CREATE TABLE objednavky_tovary (
  objednavka_id INT NOT NULL,
  tovar_id INT NOT NULL,
  pocet INT NOT NULL, # počet je číslo
  cena_za_kus INT NOT NULL, # cena tovaru se může měnit, v objednávce musí zůstat stejná
  cena_celkem INT NOT NULL # pokud by byly slevy, tak může být různá od pocet*cena_za_kus
);

A ukázka dat:
# ID za tebe vygeneruje databáze; v PHP ho pak získáš funkci něco jako: last_insert_id

# id=1 a id=2
INSERT INTO tovary VALUES (NULL, 53, 'Kniha o háčkování'), (NULL, 12, 'Pletací jehlice');

# id=1
INSERT INTO zakaznici VALUES (NULL, 'Petr', 'Chalupa', 'petr@chalupa.cz', '+420789456123');

# id=1
INSERT INTO adresy VALUES (NULL, 1, 'Klíčová 3', 'Praha 1', '10000');

# id=1
INSERT INTO objednavky VALUES (NULL, 1, 1, NOW(), 'nova', 101, NULL);

INSERT INTO objednavky_tovary VALUES (1, 1, 1, 53, 53), (1, 2, 4, 12, 48);
tomas2245
Profil
juriad:
Ďakujem ti za tvoj čas, krásne si to rozpísal :) to musím uznať...
len ešte jedna otázka, napr. u tabuľky: objednavky odkiaľ sa berie ID pre zakaznik_id a adresa_id ? aj to musí mať auto_increment nie?
CREATE TABLE objednavky (
  id INT PRIMARY KEY AUTO_INCREMENT,
  zakaznik_id INT NOT NULL,
  adresa_id INT NOT NULL,
  vytvorena DATETIME NOT NULL, # nikoli VARCHAR ani INT
  stav VARCHAR(255) NOT NULL, # často stačí i INT
  cena_celkem INT NOT NULL, # *
  poznamka TEXT # není povinná
);
martin1312
Profil
tomas2245:
Zakaznik_id je prisluchajuce konkretnemu zakaznikovi z tabulky Zakaznici a dalsie obdobne...

juriad:
Mozem sa spytat, preco je lepsie cenu ukladat v centoch do INT a nie pouzit Decimal? Napada ma rychlost vypoctov priamo v dotaze, ale je to dostatocna vyhoda? Dakujem
tomas2245
Profil
martin1312:
ako to tomu prislúcha keď hodnota toho bude furt nula? či ja nejako pomocou PHP pri zápise objednávky musím zistiť maximálnu hodnotu zakaznik_id a dať +1? JOIN-y sú u mňa novinka, ale musím sa do toho pustiť...
martin1312
Profil
tomas2245:
Pri vkladaní nových dát budeš postupovať približne takto:
1. V okamihu vytvorenia novej objednávky sú položky tovaru už vytvorené (to je logické), a teda poznáš pre každú položku z tabuľky tovar jej id (tovar.id)
2. Vytvoríš zákazníka, po vložení budeš vedieť jeho ID - zakaznici.id
3. Vytvoríš novú objednávku (teraz už budeš poznať tiež jej ID - objednavka.id), na vytvorenie objednavky použiješ zakaznici.id z predchádzajúceho kroku
4. Vytvoríš záznamy v tabuľke objednavka_tovary, jeden riadok záznamu pre každú položku, ktorá má byť objednaná. Pre vytvorenie tohto záznamu potrebuješ poznať tovar.id (do stĺpca tovar_id ) a objednavka.id (do stĺpca objednavka_id) - a tieto už poznáš, viď predchádzajúce kroky.

Toto jej hrubý postup. V realite možno v okamihu vytvorenia objednávky nebudeš vediet, ktorý zákazník ju vytvára (ešte nebol zaregistrovaný, ešte nazadal svoje údaje...), takže môžeš tie kroky jemne upraviť. Alebo môžeš vytvoriť objednávku bez vyplneného zakaznik_id a až potom, ako zákazník vyplní údaje a ty ich vložíš do databázy (z toho sa dozvieš jeho ID) ho doplniť pomocou UPDATE.

//tento postup si už musíš naprogramovať samozrejme v PHP
tomas2245
Profil
fúha, tak inak skúsim vysvetliť moju problematiku...ja nemám žiadny extra e-shop na svojej stránke ktorý by obsahoval nejaké zložité funkcie (napr. registrácie)
Je to jedna stránka na ktorej sa nachádzajú inputy s (meno, priezvisko, adresa, psc...... a aj tovar má svoj input do ktorého stačí zadať počet kusov) a to sa mi teraz ukladá do tabuľky ,,objednávky" kde mám všetko spolu od mena až po cenu tovaru...takto to aj funguje ale keďže tam mám 40 stĺpcov tak som chcel aby sa mi to ukladalo do týchto rôznych tabuliek a rozdeliť tie stĺpce...možno by sa to zoptimalizovalo alebo možno to nevadí?

Ja by som to nechal aj tak ako to je... že s jednou tabuľkou ale keďže tam je 40 stĺpcov..nebude to časom pomalé?
martin1312
Profil
tomas2245:
To nie je problém. Zákazníka vytvoríš v jednom scripte spolu s objednávkou, iba to bude skôr (vyššie) v kóde.
Na druhej strane, ak to má byť takéto uplne jednoúčelové (a žiadne registrácie ani neplánuješ zavádzať), možno by sa dalo porozmýšlať nad tým, že údaje o zákazníkovi a jeho adrese by si dal priamo do tabuľky objednávky. Spôsob priradenia tovaru ale nie, ten nechaj určite taký, ako je hore navrhované.
Je to ale proti "optimálnemu" a normalizovanému návrhu a malo by ti by jasné, že s tým môžu byť v budúcnosti problémy - ak budeš chcieť systém rozšíriť a podobne.
juriad
Profil
V tom případě zůstaň u stejného počtu tabulek jako jsi měl v návrhu, netřeba jich přidávat víc.
Ty zakaznik_id, objednavka_id musíš dodat v PHP ty.

Hodně nahrubo by to mohlo vypadat zhruba takto (zanebdal jsem escapovaní):
mysqli_query($link, "INSERT INTO zakaznici VALUES (NULL, '$jmeno', '$prizvisko' '$email', '$tel', '$ulice', '$mesto', 'psc')");
$zakaznik_id = mysqli_insert_id($link);
mysqli_query($link, "INSERT INTO objednavky VALUES (NULL, $zakaznik_id, NOW(), 'nova', $celkova_cena, NULL)");
$objednavka_id = mysqli_insert_id($link);
foreach ($tovary as $tovar) {
  mysqli_query($link, "INSERT INTO objednavky_tovary VALUES ($objednavka_id, $tovar[id], $tovar[pocet])");
}
tomas2245
Profil
Ďakujem, primárný klúč mám nastavovať u klasického id alebo napr. u zakaznik_id ? a u toho zápisu tovarov sa pridá toľko riadkov koľko je objednaných tovarov alebo sa to pridá do jedného? ak do jedného aký tvar by mal teda ten zápis v db?
martin1312
Profil
Primárny kľúč nastavovať iba u "klasického" id. Pri zápise tovarov sa pridá toľko riadkov, koľko je objednaných tovarov (juriad to naznačil v jeho kóde cyklom foreach)
tomas2245
Profil
no okej, ešte posledná otázočka, ak som to mal doteraz v jednej tabuľke všetko tak aké to má mínusy? čisto z hľadiska len optimalizácie že tam je 40 stĺpcov, veď to musí zvládať či? keď mysql dokáže až 4000+
martin1312
Profil
tomas2245:
Ako si to mal v jednej tabuľke? Viaceré produkty pre jednu objednávku si ako ukladal? Nebodaj si to nejako serializoval a do jedneho stĺpca?
tomas2245
Profil
martin1312:
áno, serializoval ale zatiaľ s tým problém nemám dokážem sa s tým vysporiadať, ale tak tento nový spôsob že každý tovar na nový riadok nie je nejaké zahlcovanie tej tabuľky?
keď napr. jeden zákazník by si objednal 50 tovarov tak zaberie 50 riadkov...to je v pohode?
Tomášeek
Profil
tomas2245:
Ano, miliony řádků nejsou pro DB problém, naopak, umí s nimi narozdíl od hafa sloupců nebo serializovaných dat pracovat bez problému.
tomas2245
Profil
okej, to som rád teda tak sa do toho teda pustím...keď budem chciet vyselectovat z tabuliek napr.: zakaznici, objednavky_info a objednavky_tovar tak ten dotaz bude vyzerať takto?
totiž neviem spojiť viac ako 2 tabuľky...

skúšal som nejak takto?

<?php

$dotaz = mysqli_query($pripoj,"SELECT *
FROM zakaznici
INNER JOIN objednavky_info ON objednavka_id = zakaznik_id
INNER JOIN objednavky_tovar ON tovar_id = zakaznik_id");

?>
juriad
Profil
Ten dotaz je skoro správně, jen máš špatně ty podmínky ON v JOINech.
Ukázka, jak to má být správně: sqlfiddle.com/#!9/a35cad/2
tomas2245
Profil
ďakujem :) dnes niečo skúsim nakódiť a keby niečo sa ozvem :)
tomas2245
Profil
miesto o.id ktore som vyznačil nemá byť o.zakaznik_id ?

a ďalšia vec do tabuľky produkty pridám stĺpec Druh v ktorom bude nape. (zośity, knihy...) a ja by som chcel potom z objednaného tovaru (jeho ID) priradiť názov z tabuľky produkty na základe aj toho druhu...ako by mohol taký dotaz vyzerať? to potom aj v objednanom tovare musí byť asi stlpec Druh..aby to bolo navzajom prepojené, pokiaľ sa nemýlim..

SELECT *
FROM zakaznici z # tabulku "zakaznici" budu ve zbytku dotazu nazývat "z" (říká se tomu alias)
JOIN objednavky o ON z.id = o.zakaznik_id # tady používám znovu aliasy; psát INNER není nutné (je to výchozí typ JOINu)
JOIN objednavky_tovary ot ON o.id = ot.objednavka_id;
juriad
Profil
Má tam být o.id. Přeci objednavka_tovar nemá nic společného se zákazníkem, objednavka_tovar souvisí s objednávkou.

Nerozumím tomu „druhu.“ Každý produkt má jeden druh? Nebo naopak jeden produkt může mít víc druhů? Možná zkus ukázat jak vypadá tabulka produktů (stačí výstup SHOW CREATE TABLE produkty;)
tomas2245
Profil
zabudni čo som písal :D už som to vyriešil..
tomas2245
Profil
ale inak, to o.id = ot.objednavka_id mi furt nedáva zmysel, to teda nemôžem záznamy mazať keby si niekto objednávku zrušil či? lebo by sa ten auto_increment navyšoval.. a by potom nesedeli id-čka..neviem či rozumieš čo mám na mysli..
juriad
Profil
tomas2245:
Nemysli si, že auto_increment dělá něco magického. Ten slouží jen k přiřazení nějakého unikátního ID. Stejně tak dobře bys mohl mít textová id, která by obsahovala názvy zvířat nebo náhodný citát. Auto_increment jen umožňuje číslená id snadno generovat. Je sice pravda, že číselná id získaná auto_incrementem s časem rostou, ale není pravda, že nebudou obsahovat mezery.

I když smažeš záznam v databázi, tak auto_increment to nikterak neovlivní - příště přiřadí číslo, které je větší, než každé dříve použité. Id zákazníka, id objednávky a id objednávka_tovaru spolu vůbec nesouvisí. Proto má každá tabulka své vlastní id, aby v nich byla úplná volnost.

V ukázce sqlfiddle.com/#!9/103334/1 jsem přiřadil id záznamům ručně (auto_increment se uplatní jen, když je id není v insertu vypněné). Přestože jsou ta čísla divná, všechny dotazy fungují úplně stejně jako v předchozí verzi.
tomas2245
Profil
a keď to mám jednkstránkové že sa zákaznik neregistruje ale je to proste len formulár... a ako ukladám zakaznik_id tak by som tú hodnotu ulozil aj pre objednavka_id? a bola by všade rovnaká? to mi príde logickejšie..
juriad
Profil
tomas2245:
Teď to možná máš jednostránkové, ale nemusí tomu tak být navěky.
Pokud chceš, můžeš si id zákazníka nechat vygenerovat auto_incrementem, a pak id objednávky nastavit (v INSERTu) na stejné id. Pak budeš mít v tabulce objednvaky dva sloupce se stejnou hodotou (id, zakaznik_id), ale to ničemu nevadí a já bych je tam raději nechal (třeba se to bude časem hodit).
tomas2245
Profil
no okej a tak teda primarny kluc v tomto pripade ako to chcem robit tak bude primarny aj zakaznik_id v tej tabulke objednavky ci? a ešte jedna vec by ma zajímala. Tovar ukladám do tabuľky objednavky_tovar tam mám tiež zakaznik_id s hodnotou z tabuľky zakaznici...

a v tej tabuľke objednavky_tovar mám stĺpce: zakaznik_id, nazov a pocet

a ako mám vypísať ten tovar potom aby mal svoj názov a počet nejak pomocou foreachu tipujem, ale nejak sa mi nedarí prísť na tvar ako by to malo vyzerať..
juriad
Profil
Primární klíč je jen id. Zakaznik_id je obyčejný sloupec, který shodou okolností obsahuje to samé jako id.
Tabulka objednavky_tovar nemá se zákazníkem vůbec nic společného, tato tabulka má vazbu na objednávku (proto obsahuje objednavka_id), nemá obsahovat zakaznik_id (ty se jej tam snažíš vnutit, protože tušíš, že zakaznik_id = objednavka_id).

Pokud tě zajímá jaké tovary si zákazník (s id 123) objednal (aniž by tě zajímalo něco jiného), bude dotaz vypadat takto:
SELECT ot.*
FROM objednavky_tovar ot
JOIN objednavky o ON ot.objednvaka_id = o.id
WHERE o.zakaznik_id = 123;

Pokud id objednávky je to samé jako id zákazníka, bude fungovat i toto (ale rád bych tě od toho odradil):
SELECT ot.*
FROM objednavky_tovar ot
WHERE ot.objednavka_id = 123;

Toto je snad i odpovědí na to, jak vypsat tovary z objednávky.
tomas2245
Profil
okej, ďakujem ti veľmi veľmi moc, že si mi takto ochotne pomáhal dal si mi rady nad zlato :) dám si všetko dokopy a snáď úspešne sa mi podarí všetko spojazdniť :)
tomas2245
Profil
neviem no, dotaz som urobil takto:
<?php

$vobj = mysqli_query($pripoj,"
SELECT meno, priezvisko, mesto, ulica, cislodomu, psc, email, zaslanie, telefon, celkova_cena, vytvorena, nazov, pocet 
FROM objednavky_zakaznik oz 
JOIN objednavky_info oi ON oz.id = oi.zakaznik_id 
JOIN objednavky_tovar ot ON oi.id = ot.objednavka_id
JOIN objednavky_cena oc ON ot.id = oc.objednavka_id 
WHERE oi.zakaznik_id='$idecko'");

?>

a neviem prísť teraz ako by som mal vytiahnuť stĺpce tovaru: názov a pocet..keďže chcem vytiahnuť viacero hodnôt ale neviem ako..


//vyriešené
tomas2245
Profil
všetko mám už hotové nakoniec mi zostáva prehodiť staré objednávky do nových tabuliek...existuje nato nejaký dobrý spôsob aby som sa čo najmenej narobil? je tam cca 300 riadkov...a ja potrebujem jednotlivé stĺpce s menami, priezviskami.... prehodiť do nových tabuliek..samozrejme aby sa zachovalo id zo starých tabuliek a zapísalo do nových aby sa nestalo že napr. že tovar bude patriť inému zákazníkovi...
« 1 2 »

Vaše odpověď

Mohlo by se hodit


Prosím používejte diakritiku a interpunkci.

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