Autor Zpráva
Andrej.B
Profil
Zdravim,
mam databazu, kde su tieto 4 tabulky: vyrobna_zakazka, podsivka, druh, zakaznik
Kod nizsie funguje a vypise, co ma...
Vyberam podla vyrobna_zakazka: zakaznik, druh, podsivka...
Nakolko to chcem mat uzivatelsky prijemne a chcem vypisat nazov z tabulie zakaznik, druh, podsivka , nielen ako cisla, ale pekne menom...
Predsa len ukazat uzivatelovi ze ma zakazku cislo 6003537 a tam zakaznik 1, a druh 5 nieje uzivatelsky privetive.
Moja otazka znie... Ide to aj nejako lepsie? Uz takto sa mi vidi po spojeni s frontend dost tazkopadne.

Dakujem


<?php
$id_vyrobna_zakazka = '6003537';
$result1 = $conn->query("SELECT * FROM vyrobna_zakazka WHERE id_vyrobna_zakazka = ".$id_vyrobna_zakazka."");
    while ($row1 = $result1->fetch_assoc()) 
    {
    
        $result2 = $conn->query("SELECT * FROM zakaznik WHERE id_zakaznik = ".$row1['id_zakaznik']."");
        $result3 = $conn->query("SELECT * FROM druh WHERE id_druh = ".$row1['druh']."");
        $result4 = $conn->query("SELECT * FROM podsivka WHERE id_podsivka = ".$row1['podsivka']."");
    }
            while ($row2 = $result2->fetch_assoc()) 
                {
                echo $row2['meno_zakaznik'].' - '; //vypise meno zakaznika z tabulky zakaznik
                    
                }
            while ($row3 = $result3->fetch_assoc()) 
                {
                echo $row3['nazov_druh'].' - ';//vypise nazov druhu
                    
                }
            while ($row4 = $result4->fetch_assoc()) 
                {
                echo $row4['druh_podsivka'].' - ';
                    
                }
        ?>

DATABAZA

        
CREATE TABLE `vyrobna_zakazka` (
  `id_vyrobna_zakazka` int(11) NOT NULL,
  `id_zakaznik` int(11) NOT NULL,
  `druh` text COLLATE utf8_bin NOT NULL,
  `podsivka` tinytext COLLATE utf8_bin NOT NULL,
)

CREATE TABLE `podsivka` (
  `id_podsivka` int(11) NOT NULL,
  `druh_podsivka` varchar(255) COLLATE utf8_bin NOT NULL,
  `info_podsivka` varchar(255) COLLATE utf8_bin NOT NULL
)

CREATE TABLE `druh` (
  `id_druh` int(11) NOT NULL,
  `nazov_druh` varchar(255) COLLATE utf8_bin NOT NULL,
  `info_druh` text COLLATE utf8_bin NOT NULL
) 

CREATE TABLE `zakaznik` (
  `id_zakaznik` int(11) NOT NULL,
  `meno_zakaznik` varchar(255) COLLATE utf8_bin NOT NULL,
  `ico` int(11) NOT NULL,
  `text` text COLLATE utf8_bin NOT NULL
)        
Radek9
Profil
Andrej.B:
Join?

SELECT vz.*, p.druh_podsivka, d.nazov_druh, z.meno_zakaznik
FROM vyrobna_zakazka vz
JOIN podsivka p ON p.id_podsivka = vz.podsivka
JOIN druh d ON d.id_druh = vz.druh
JOIN zakaznik z ON z.id_zakaznik = vz.id_zakaznik
WHERE id_vyrobna_zakazka = :id
Kcko
Profil
A ještě doplním, chápeš co dělá while?
Kajman
Profil
Pokud by spojení nebylo vždy 1:1, tak mrkněte na
Srovnání dotazů do závislých tabulek
Andrej.B
Profil
Radek9:

tento zapis je pre mna dost nepochopitelny. Co znamena: Select vz.* , ci p.druh_podsivka, pravdepodobne len skratky? Ma tam byt podsivka.druh_podsivky? Viem len id_vyrobna_zakazka z tabulky vyrobna_zakazka a potrebujem druh_podsivka,meno_zakaznik a nazov_druh. Ako potom z takehoto zapisu dostanem vysledok?
Dik za trpezlivost

Kcko:
da mi vysledok do pola? z ktoreho si potom vyberiem, co potrebujem? Asi to nieje koser, kedze potrebujem vzdy len jeden riadok, teda aspon na tomto priklade to tak je...

Kajman:
podla clanku to mam dost neefektivne.. horsie je ze logiku tych JOIN prikazov horsie chapem.
Taps
Profil
Andrej.B:
pokud vybiras jen jeden zaznam tak je while zbytecne. while muzes pouzit kdyz vybiras 2 a vice zaznamu z databaze


p.druh_podsivka ( p = alias, da se rict ze je to zkraceny nazev pro databazovou tabulku) misto aby jsi pouzil podsivka.druh_podsivky tak staci zapis p.druh podsivky
Radek9
Profil
Andrej.B:
pravdepodobne len skratky? Ma tam byt podsivka.druh_podsivky?
Nikoli, jsou to aliasy. Jsou definovány na řádcích 2–5. Takže nic měnit nemusíš, tohle je funkční kód. Pouze musíš dosadit :id. Buď pomocí prepared statementu nebo pomocí spojení stringu, jako to máš teď (v tomhle případě to id ale nezapomeň ošetřit, pokud pochází od uživatele).

Ako potom z takehoto zapisu dostanem vysledok?
Ten můj dotaz vybírá všechny sloupce z té první tabulky a potom ty tři konkrétní sloupce z ostatních. Takže k nim prostě jenom přistoupíš:

<?php
$id_vyrobna_zakazka = 6003537;
$result = $conn->query('
  SELECT vz.*, p.druh_podsivka, d.nazov_druh, z.meno_zakaznik
  FROM vyrobna_zakazka vz
  JOIN podsivka p ON p.id_podsivka = vz.podsivka
  JOIN druh d ON d.id_druh = vz.druh
  JOIN zakaznik z ON z.id_zakaznik = vz.id_zakaznik
  WHERE id_vyrobna_zakazka = ' . $id_vyrobna_zakazka
);
$row = $result->fetch_assoc();

echo $row['meno_zakaznik'] . ' - ' . $row['nazov_druh'] . ' - ' . $row['druh_podsivka'];
Kajman
Profil
Andrej.B:
V tabulce vyrobna_zakazka je správně sloupec zákazník jako číslo, ale špatně druh a podšívka jako text, pak se ne to nemusí správně propojit s id druhu a id pošívky.
Andrej.B
Profil
Taps:
ok, myslel som si.. je to vlastne len kopirovane z ineho stareho projektu /8 rokov som neprogramoval/, zacal som sa zase vzdelavat :)

Radek9:

budem to musiet preluskat nejako, a asi hlavne prerobit trocha tie tabulky, kedze su dost neprehladne (meno_zakaznik vs nazov_druh (malo by byt skor meno_druh) a podobne), ale vypada to super, ze mozem aj inde potom pouzit tieto premenne /$row['meno_zakaznik']/, co vypadnu po dotaze. Osetrenie premennych pouzivam
$id_vyrobna_zakazka = HTMLSpecialChars($_POST['id_vyrobna_zakazka']);
+ obykla kontrola formu, ci je to cislo, kolko ma znakov a podobne.

Kajman:
ako som pisal vyssie, troska prerobim tie polia tabuliek, aby to bolo viac prehladne.

Dakujem moc, dost ste mi pomohli a urcite to nebude naposledy :)

Andrej
Radek9
Profil
Andrej.B:
Osetrenie premennych pouzivam
To je fajn na ošetření textových HTML vstupu, ale neřeší to ošetření SQL injection. Speciálně pro textové vstupy používej ještě mysqli_real_escape_string. U čísel naopak nemusíš používat tebou používanou funkci. Mělo by stačit zkontrolovat, jestli je to opravdu číslo.
Keeehi
Profil
Radek9:
To je fajn na ošetření textových HTML vstupu
Spíš by se to mělo používat u výstupů do HTML.
Kajman
Profil
No z databáze se veznou data - tento vstup se escapováním upraví pro korektní html výstup :-)
Andrej.B
Profil
pokial mam kod:
$result22 = $conn->query("SELECT * from balik WHERE id_vyrobna_zakazka = ".$id_vyrobna_zakazka." ORDER BY cislo_balik DESC LIMIT 1");
         
        while ($row33 = $result22->fetch_array()) 
             {
    $cislo_balik = $row33['3']+1;
    
              }

tak zoberie z DB najvacsie cislo_balik podla $id_vyrobna_zakazka a pripocita 1, pokial tam zatial ziadn zaznam nieje, vyhodi chybu:
Incorrect integer value: '' for column 'cislo_balik' at row 1, kedze nemoze vlozit prazdnu premennu $cislo_balik.
Nizsie je iba Insert, ktory pracuje spravne, ked je pocet riadkov minimalne 1
ako dosiahnut toho, ze ked vrati prazdny pocet riadkov z DB aby pripocitalo +1. Skusal som vsemozne IF ELSE v spojeni s $result22->num_rows; ale stale vypisuje rozne chyby.
POtrebujem docielit toho aby premena $cislo_balik bola +1 ako najvyssia cislo_balik v DB a ak nie je ziadn zaznam tak da 1

uf neviem ci som to dobre napisal.

diky
Kajman
Profil
if ($row33 = $result22->fetch_array()) 
{
    $cislo_balik = $row33['3']+1;
}
else
{
    $cislo_balik = 1;
}         
Keeehi
Profil
Andrej.B:
Úplně si nejsem jistý zda ti rozumím, ale možná to trefím. Nemáš náhodou prehozené pořadí toho selectu a insertu? Když vyžaduješ aby při selectu jsi měl 1+ záznamů neměl by být ten insert před selectem?
Andrej.B
Profil
Kajman:
ked sa do da zlozito, naco to robit jednoducho :) Super... ja som este urobil nakoniec takto, ale vase je krajsie ...

 $row_cnt = $result22->num_rows;
             if($row_cnt==0) {  $cislo_balik = 1; } 
    else {     while ($row33 = $result22->fetch_array()) 
             {
    $cislo_balik = $row33['3']+1;
    
              }
    }

Keeehi:
najskor sa pozriet do DB ci tam vobec je balik a az potom dat +1... mam to tazkopadne nakolko cislo balika sa nakoniec sklada ako cislo zakazky 6006363 + cislo balika, ktore je 001 ... 002 atd... Cize cislo balika je nakoniec 6006363001 ... co je dane historicky... Netusil som ako to spravit v DB, takze takto sa mi to videlo najednoduchsie. mam V DB polozku :
`cislo_balik` tinyint(3) UNSIGNED ZEROFILL NOT NULL,
ktora mi pridava ku kazdemu cislo 1-9 dve 0 a ak je nad desat tak 1... cez rozne podmienky sa mi to nechcelo a takto to funguje :)
Andrej.B
Profil
Zdravim,

minuly kod isiel tak ako mal, ale troska som updatoval cely script aj logiku usporiadania...
Teraz mam
$id_vyrobna_zakazka = $_GET[zakazkaid];
$result = $conn->query("
  SELECT vz.*,  z.meno_zakaznik, d.nazov_material
  FROM vyrobna_zakazka vz
  JOIN zakaznik z ON z.id_zakaznik = vz.id_zakaznik
  JOIN sklad_material d ON d.id_material = vz.id_top 

  WHERE id_vyrobna_zakazka = '".$id_vyrobna_zakazka."'");

$row = $result->fetch_assoc();
 
echo $row['meno_zakaznik'];
echo $row['nazov_material']; // vyberie ten id_top 

meno_zakaznika vyberie dobre. Potom mi vybera aj z tabulky sklad_material - id_top, vyberie dobre... lenze v tabulke vyrobna_zakazka mam okrem id_top aj id_middle a id_down, to je vlastne z coho sa sklada ten vyrobok... Ako to mozem urobit v tom selecte z databazy aby to vedelo, ze berie vsetky tri id_top,id_middle, id_down

vyberie mi len ten prvy ako echo $row['nazov_material'];
Ako mam na ten Join v databaze ist? Skusal som rozne
JOIN sklad_material d ON d.id_material = vz.id_top OR d.id_material = vz.id_middle ale neviem ako to urobit takto v jednom dotaze ten vypis cez $row[]

tabulka vyrobna_zakazka
CREATE TABLE `vyrobna_zakazka` (
  `id_vyrobna_zakazka` int(11) NOT NULL,
  `id_zakaznik` int(11) NOT NULL,
  `id_top` int(11) NOT NULL,
  `id_middle` int(11) NOT NULL,
  `id_down` int(11) NOT NULL,
  `odpocet_chyby` float NOT NULL DEFAULT '0.25',
  `datum_zakazka` int(11) NOT NULL,
 
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

diky za rady
Kajman
Profil
Můžete připojit třikrát tu stejnou tabulku, stačí použít jiné aliasy. Jistější bude left join. Pak i vybíranému sloupci s názvem dejte různé aliasy.

Něco jako
SELECT vz.*,
       z.meno_zakaznik,
       mt.nazov_material nazov_top,
       mm.nazov_material nazov_middle,
       md.nazov_material nazov_down
FROM   vyrobna_zakazka vz
       LEFT JOIN zakaznik z
              ON z.id_zakaznik = vz.id_zakaznik
       LEFT JOIN sklad_material mt
              ON mt.id_material = vz.id_top
       LEFT JOIN sklad_material mm
              ON mm.id_material = vz.id_middle
       LEFT JOIN sklad_material md
              ON md.id_material = vz.id_down
WHERE  id_vyrobna_zakazka = '$id_vyrobna_zakazka'  

Ale možná by tomu slušela samotná vazební tabulka místo těch tří sloupců, abyste mohl mít libovolný počet materiálů k jedné zakázce.
Andrej.B
Profil
wau... tie aliasy som skusal vseliako, len mi to chyby hadzalo... Diky...

Pri tvoreni vyrobnej zakazky si vyberam vrchny, stredny a spodny material ... mozem mat nekonecno /cca 200x40x20/ roznych variacii materialov. A takto mam prehlad, kolko materialu ktoreho sa minulo... Skusal som si zadefinovat material z tych 3 roznych , ze budem mat v tabulke vyrobna_zakazka polozku id_laminat a ten by bral z tabulky laminat tieto tri id_top, id_middle a id_down , ale to by znamenalo , ze by som musel mat tieto laminaty uz dopredu urobene a bolo by ich velmi vela a mal by som to uz moc rozbite a osobne pre mna dost neprehladne potom robit na to selecty do statistiky a podobne... Uz teraz mam problem len vytvorit poriadny dotaz na db :)
Ale viem, ze toto este nieje definitivne ...

super diky moc

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:

0