Hei taas.
Päätin aloittaa uuden aiheen koska vanha otsikko ei enää vastannut ongelmaa.
https://www.ohjelmointiputka.net/keskustelu/19091-mysql-virhe-left-join-kyselyssä
Tällä koodini tulostaa listan kappaleista ja soittolistoista sekä tiedon millä soittolistoilla kappale on hienoon checkbox taulukkoon. (Kiitos Metabolixin!)
kappale main hitti hidas poison x x sweet child.. x x juupijuu x nönnöö jne..
Ongelmani on siis sellainen että nyt jos ruksin esimerkiksi kappaleen nönnöö mainiin ja kappaleen juupijuu hitiksi, pitäisi saada myös tiedot tallennettua tietokantaan.
tiedot ovat kolmessa eri tietokannassa seuraavanlaisesti:
songlist
-ID
-artist
-title
-album
-trackno
categorylist
-ID
-songID //sama kuin songlist.ID
-categoryID
-sortID
category
-ID
-name
-parentID
-levelindex
-itemindex
Annan vielä tämänhetkisen koodini:
<?php include ("kaplista.php"); // Get the search variable from URL $artistit = @$_POST['artist'] ; mysql_connect( "**********", "****", "*********" ); mysql_select_db( "samdb" )or die( "Ei pygee valitsee databeissii" ); // Haetaan categorylist $cat = mysql_query( " SELECT * FROM category" ) or die('Error: ' . mysql_error()); $category = array(); while ($x = mysql_fetch_assoc($cat)) { $category[$x["ID"]] = $x; } mysql_free_result($cat); // Haetaan songlist $son = mysql_query( " SELECT artist, album, title, trackno, ID, ( SELECT GROUP_CONCAT(DISTINCT categoryID ORDER BY categoryID SEPARATOR ',') FROM categorylist WHERE categorylist.songID = songlist.ID ) AS 'categorylist' FROM songlist WHERE songlist.songtype LIKE 'S' AND songlist.status LIKE '0' AND songlist.artist LIKE '$artistit' ORDER BY artist, album, trackno" ) or die('Error: ' . mysql_error()); $songlist = array(); while ($y = mysql_fetch_assoc($son)) { $songlist[] = $y; } mysql_free_result($son); $songs = array(); foreach ($songlist as $song) { // Puretaan kategorialista taulukoksi, jossa category.ID on avaimena $song["categorylist"] = array_flip(explode(",", $song["categorylist"])); // Merkataan puuttuviin kategorioihin false ja löytyineisiin true foreach ($category as $id => $c) { $song["categorylist"][$id] = isset($song["categorylist"][$id]); } $songs[$song["ID"]] = $song; } unset($songlist); // Tulostellaan echo "<h2>Haetut Kappaleet:</h2>"; // Otetaan kategorioiden määrä ja ID:t talteen $cat_count = count($category); $category_id_arr = array_keys($category); echo "<table>\n"; // Tulostetaan otsikkorivi: artisti, albumi, kappale, kategoriat, ... echo "<thead><tr><th>artisti</th><th>albumi</th><th>kappale</th>"; foreach ($category as $c) { echo "<th>{$c["name"]}</th>"; } echo "</tr></thead>\n"; // Tulostetaan kappaleet: echo "<tbody>\n"; $artist = $album = null; foreach ($songs as $row) { // Tarvittaessa uusi artisti if ($artist != $row["artist"]) { $artist = $row["artist"]; $album = null; // <td colspan='$cat_count'></td> vie tilaa kategoriasolujen verran. echo "<tr><td class='artist' colspan='3'>$artist</td><td colspan='$cat_count'></td></tr>"; } // Tarvittaessa uusi levy if ($album != $row["album"]) { $album = $row["album"]; echo "<tr><td></td><td class='album' colspan='2'>$album</td><td colspan='$cat_count'></td></tr>\n"; } // Kappaleen tiedot echo "<tr><td></td><td></td><td class='song'>{$row["title"]}</td>"; // Kappaleen kategorialaatikot foreach ($category_id_arr as $cat_id) { $checked = $row["categorylist"][$cat_id]; if ($checked) $checked = " checked"; else $checked = ""; echo "<td><input type='checkbox' name='check[{$row["ID"]}][$cat_id]' $checked></td>"; } echo "</tr>\n"; } echo "</tbody>\n"; echo "</table>\n"; ?> </table> </body> </html>
Toki osaan tehdä formin jolla lähetetään uutta tietoa tietokantaan, mutta en keksi miten pitäisi tämän kanssa lähteä liikkeelle. Joten joudun taas kerran pyytämään nöyrästi apua.
apua!?
PS. jos haluatte käydä vilkaisemassa miltä tulos näyttää. Alla linkki (toimii jostain syystä vain IE:llä tai ei ainakaa FF näytä listaa.)
http://www.stageradio.com/kaplista.php
Suosittelen validia HTML:ää ja validaattorin käyttöä. Datan listautumisessa on ongelmana, että koodistasi puuttuu =-merkki. Olisit voinut todeta tämän itse ihan HTML-koodia vilmaisemalla: <option value'3 Doors Down'>, <option value'AC/DC'> jne.
Enemmänkin on syytä hämmästellä, että jostain syystä tuo IE:llä kuitenkin toimii. O_o
Muistahan myös tulostaessasi käyttää htmlspecialchars-funktiota.
Itse ongelmaan: Olisi aika tyhmää päivittää sadan kappaleen tiedot, jos vain yhtä on muutettu. Toisaalta alkuun voit aivan hyvin tehdä päivityksen niinkin, ehdit kyllä miettiä sitä vielä monta yötä.
Nythän checkboxit on nimetty niin, että kun data lähetetään, saat niistä suoraan songID-categoryID-parit, jotka kantaan täytyisi saada.
Vaihtoehdot ovat siis ilmeisesti:
1. Taulusta categorylist poistetaan ensin kaikki rivit, joiden kappaleiden esittäjä on käsiteltävä esittäjä. Sitten tauluun lisätään rivejä sen mukaan, mitä valintaruutuja on valittu. Eli koko taulu categorylist käsiteltävän esittäjän osalta rakennetaan alusta asti uudestaan.
2. Taulusta categorylist poistetaan rivit, joita vastaavat valintaruudut oli valittu lomakkeen tulostushetkellä ja joiden valinnan käyttäjä poisti. Sitten tauluun lisätään rivit, joita vastaavia valintaruutuja ei ollut valittu lomakkeen tulostushetkellä ja jotka käyttäjä valitsi.
Vaihtoehto 1 on helpompi toteuttaa mutta voi rasittaa tietokantaa. Vaihtoehto 2 on vaikeampi toteuttaa mutta ei tee turhia muutoksia tietokantaan.
Jos ymmärsin kysymyksesi niin vastaan:
UPDATE table SET hitti = '$hitti', main = '$main', hidas = '$hidas' WHERE id = '$id'
janijohannes kirjoitti:
Jos ymmärsin kysymyksesi niin vastaan:
Et ymmärtänyt kysymystä. Eihän taulussa edes ole noin nimettyjä kenttiä, vaan kategoriat ja kappaleet on yhdistetty taululla, jossa on aina kappaleen ID ja kategorian ID. Joka kappaleella on tietenkin yhtä monta riviä kuin valittua kategoriaakin.
(Ei millään pahalla, mutta ehkä sinun pitäisi aina miettiä vähän pidempään, oletko ymmärtänyt kysymyksen ja tiedätkö asiasta tarpeeksi auttaaksesi. Olet viime aikoina monessa keskustelussa "neuvonut" aivan päin honkia, ja omat kysymyksesi ovat yleensä tätäkin helpompia.)
Antti Laaksonen kirjoitti:
Vaihtoehto 1 on helpompi toteuttaa mutta voi rasittaa tietokantaa. Vaihtoehto 2 on vaikeampi toteuttaa mutta ei tee turhia muutoksia tietokantaan.
Ei jälkimmäinenkään kovin vaikea ole. Sen voi toteuttaa suunnilleen näin (osittain pseudokoodia):
<?php $new_cats_list = implode(",", array(/* kaikki uudet categoryID:t */)); $cat_id_arr = array(/* ne uudet categoryID:t, joita ei ennen ollut */); $use_old = true; foreach ($cat_id_arr as $c) { # jos vanhoja on ehkä jäljellä if ($use_old) { # yritetään päivittää yksi vanha (vääränlainen) uudeksi; # paluuarvona onnistuminen eli tieto, vieläkö niitä vääriä oli $use_old = mysql_query( "UPDATE categorylist SET categoryID = $c WHERE categoryID NOT IN ($new_cats_list) AND songID = $songID LIMIT 1" ); } # jos vääriä ei ole (tai loppuivat; siksi ei käytetä elseä vaan on uusi if) if (!$use_old) { # lisätään uusi rivi mysql_query("INSERT categorylist SET songID = $songID, categoryID = $c"); } } # poistetaan rivit, joilla on vielä väärä ID mysql_query("DELETE FROM categorylist WHERE categoryID NOT IN ($new_cats_list)"); ?>
Teillä kyllä on aina vastaukset valmiina :D Taidan jopa ymmärtää periaatteen miten tuo toimii :)
Tällä hetkellä, kun listani listautuu artistin mukaan, joten ymmärtääkseni ainakin categorialistan poistamista pitää rajoittaa esimerkissäsi. Muutenhan kaikki muut artistit katoavat listalta. vai?
Mietin kanssa että mitähän ohjelma tykkää jos se on päällä ja hakee seuraavaa kappaletta soittolistalta samaan aikaan kun tätä päivitystä tehdään listalle. Tuskin mitään maata mullistavaa?
Ja tosiaan, yksi vaihtoehto olisi tietenkin tehdä vaikka jokaisen kappaleen perään nappula mistä kappaleen tiedot voisi päivittää.
Miinus puolena tulee vastaan tietenkin se, että joka kerralla kun nappia painaa, mennään tietysti toiselle sivulle ja kappaleet pitää listata uudelleen. Ellei sitten ole mahdollista jotenkin tehdä ikäänkuin tehdävä jonoa(muistia suoritettavista tehtävista) ja sitten kun kaikki tarvittava on muokattu suorittaa se. :) .. Onkohan edes järkevää / mahdollista...
Jos hyödyntäisi ajaxia niin ei kaiketi tarvitsisi sivua uudelleen laitailla? se on kuitenkin niin vierasta itselleni joten jätettäköön myöhemmäksi :)
Ja vielä viimoiseksi kysäisen että kun checkboxissa on ID:itten pari nii miten saan ne eroteltua päivittelykoodiin?
Tässä tuli varmasti monta tyhmää kysymystä, yrittäkää kestää :)
stageradio kirjoitti:
Mietin kanssa että mitähän ohjelma tykkää jos se on päällä ja hakee seuraavaa kappaletta soittolistalta samaan aikaan kun tätä päivitystä tehdään listalle. Tuskin mitään maata mullistavaa?
No sehän riippuu pikkuisen, mitä lukituksia ja kursoreita käytät. Käytännössä varmaan mullistavimmat mitä tuosta voi tapahtua on se, että rivi poistuu tulosjoukosta sen jälkeen kun olet tehnyt haun (dynaaminen palvelinpään kursori) tai sitten jos lukupuolella käytät lukitusta niin päivitys odottaa, tai aikarajojen ylittyessä epäonnistuu. Tuota poistumista hauan jälkeen tuskin edes mitenkään huomaisit rivi kerrallaan lukiessa.
Käytännössä jos käytät noita "normaalisti" niin ei tapahdu mitään ihmeellistä.
Checkboxit on nyt nimetty niin, että ne välittyvät PHP:lle taulukkoina. Lähetyksen tulos on tällä hetkellä sama kuin seuraavan koodin luoma taulukko:
<?php $_POST["check"] = array( # kappaleen ID "24" => array( # rastittujen kategorioiden ID:t "3" => "on", "7" => "on", "9" => "on" ) # kappaleen ID "25" => array( # rastittujen kategorioiden ID:t "3" => "on", "4" => "on" ) );
Näitä voit helposti käsitellä foreach-silmukalla (ks. PHP-opas) ja muilla taulukkofunktioilla (ks. PHP:n dokumentaatio, array_keys). Aiemmin valitut kappaleet voit hakea tietokannasta, tai jos mieluummin kuormitat nettiyhteyttä, niin voit toki tulostella ne checkboxien viereen hidden-inputteihin samalla tavalla nimettyinä (tietenkin nimeksi jotain muuta kuin "check").
Suorastaan loistavaa. Olet siis jo tämänkin ottanut huomioon.
Enään minun täytyy siis opettaa itseäni käyttämään noita hyväkseni.
En voi muuta kuin kiittää.
Otan sitten taas suunnan tänne jos ilmenee ongelmia asian suhteen :)
Kiitos.
Päädyin tuohon ensimmäiseen vaihtoehtoon. Tämä saa luvan kelvata vaikka rasittaahan tuo enemmän tietokantaa ja tekee turhia muutoksia, mutta tämän osasin tehdä "ihan" itse :D
Nyt voinkin sitten tyytyväisin mielin jatkaa radion kehittämistä muilta osin!
Suur-kiitos kaikille auttajille!
Aihe on jo aika vanha, joten et voi enää vastata siihen.