Kirjautuminen

Haku

Tehtävät

Keskustelu: Ohjelmointikysymykset: PHP Mysql -matriisi

mercier [11.10.2019 13:41:12]

#

MySQL tietokannassa on kaksi taulua
- TUOTTEET, jossa on sarakkeet Tuotenimitys, Hinta ja Saldo
- TILAUKSET, jossa on Tilaajatunnus, Tuotenimitys ja Kpl.
Näytölle tulostetaan taulukko, jossa on sarakkeina Tuotenimitys ja riveinä Tilaajatunnus sekä soluissa arvona Kpl. Osa soluista jää tyhjäksi.
Nyt on ratkaistu niin, että jokaisen solun kohdalla tehdään kaksi tietokantakyselyä; $query1 = "SELECT * FROM TUOTTEET... ja $query2 = "SELECT * FROM TILAUKSET... jne. Tähän täytyy olla joku kätevämpi tapa? Tuli vastaan, kun ratkaisua hieman päivitetään muuten.

Grez [11.10.2019 15:53:42]

#

mercier kirjoitti:

Tähän täytyy olla joku kätevämpi tapa?

Juu, sitä kutsutaan JOINiksi.
https://dev.mysql.com/doc/refman/8.0/en/join.html

Metabolix [11.10.2019 16:43:14]

#

Kyselyyn voi yksinkertaisesti laittaa monta taulua. Jos ensimmäisessä taulussa on rivit 1, 2 ja 3 ja toisessa taulussa rivit A, B ja C, tuloksiin tulevat kaikki näiden yhdistelmät eli rivit 1A, 1B, 1C, 2A, 2B, 2C, 3A, 3B ja 3C. Tuloksia voi sitten rajata normaalisti ehdoilla kyselyn WHERE-kohdassa. Tässä tapauksessa rajaukseen kuuluu, että sarake Tuotenimetys olisi molemmissa tauluissa sama.

Kahdesta taulusta tietoja hakeva kysely voisi näyttää tältä:

SELECT *
FROM TUOTTEET tu, TILAUKSET ti
WHERE tu.Tuotenimetys = ti.Tuotenimetys

Toisaalta tarkemmin katsoen huomataan, että tässä ei edes käytetä TUOTTEET-taulun tietoja mihinkään eli riittäisi hakea kaikki tiedot pelkästään TILAUKSET-taulusta.

SELECT * FROM TILAUKSET

Jos kuitenkin halutaan mukaan myös ne tuotteet, joille ei ole yhtään tilausta, täytyisi käyttää LEFT JOIN -rakennetta. Tällöin valitaan kaikki rivit ensimmäisestä taulusta ja kaikki yhdistelmät toiseen tauluun, mutta jos jollekin riville ei löydy yhtään ehdon täyttävää yhdistelmää, palautetaan kuitenkin ensimmäisen taulun rivi ja toisen taulun sarakkeissa vain NULL-arvot.

SELECT *
FROM TILAUKSET ti
LEFT JOIN TUOTTEET tu ON tu.Tuotenimetys = ti.Tuotenimetys

Tietoja voisi käsitellä näin:

// Haetaan kaikki data valmiiksi em. kyselyllä.
$data0 = aja_yllä_oleva_kysely();

// Järjestetään data käytännölliseen muotoon.
$data = [];
foreach ($data0 as $d) {
	$data[$d["Tuotenimetys"]][$d["Tilaajatunnus"]] = $d["Kpl"];
}

// Taulukon solun ei tarvita enää tietokantahakua:
$tuotenimetys = "Petteri";
$tilaajatunnus = "Keijo";
$kpl = $data[$tuotenimetys][$tilaajatunnus] ?? null;

mercier [11.10.2019 17:23:46]

#

Metabolix kirjoitti:

...
Jos kuitenkin halutaan mukaan myös ne tuotteet, joille ei ole yhtään tilausta, täytyisi käyttää LEFT JOIN -rakennetta. ...

Tässä se ongelma juuri tuli, kun olin tarjoamassa supistettua taulukkoa.
Taulukossa tarvitaan kaikki tuotteet ja kaikki tilaukset.
Itse asiassa tarkentui, että tarvitaan myös ne TILAAJATUNNUKSET, joissa ei ole yhtään tilausta ja TUOTTEET, joista ei ole yhtään tilausta.
TILAUKSET taulussa on tältä osin siis myös tyhjiä rivejä ja TILAUKSET taulukon parempi nimi olisi TILAAJAT.
Paljonkohan tämä vaikuttaakaan tapaukseen, saa nähdä.
Kiitokset molemmille. Nyt siis JOINaamaan.

Metabolix [11.10.2019 17:30:59]

#

Ehkä selvin ratkaisu on hakea ei-tyhjät rivit ja käsitellä ne edellä antamani koodin tyylisesti ja sitten hakea erikseen silmukoita varten listat tilaajista ja tuotteista (kuten sinulla varmaan jo on).

The Alchemist [11.10.2019 19:26:01]

#

Kuulostaa kyllä todella oudolta, että nuo kaksi täysin eri asiaa pitäisi saada ängettyä samaan kyselyyn. Kaikkea ei pidä yrittää pupeltaa yhteen sql-kyselyyn, koska se ei usein ole edes suorituskykyisin vaihtoehto.

Vastaus

Aihe on jo aika vanha, joten et voi enää vastata siihen.

Tietoa sivustosta