Minulla on lista tapahtumista MySQL:ssä tähän tapaan:
+------+--------+------+--------------+----------------------+ | tid | month | day | title | timestamp | +------+--------+------+--------------+----------------------+ | 1 | 03 | 11 | Konsertti | 2008-05-03 11:57:58 | | 2 | 04 | 09 | Talkoopäivä | 2008-05-03 11:59:08 | | 3 | 04 | 09 | Pullakahvit | 2008-05-03 11:59:32 | | 4 | 08 | 29 | Rantaloma | 2008-05-03 12:00:09 | +------+--------+------+--------------+----------------------+
tid
on siis auto_increment-ID tiedolle, month
tapahtuman päivämäärän kuukausi, day
tapahtuman päivämäärän päivä, title
tapahtuman nimi ja timestamp
tapahtuman lisäämispäivä hallintapaneelista.
Pohja on vanha, ja nyt kun katselin sitä sivuston uudelleenkirjoituksen yhteydessä, huomasin systeemin olevan idioottimainen. Se ei esim. kerro tapahtuman kellonaikaa.
Tarkoitus olisi muuttaa taulu tällaiseen muotoon:
+------+----------------------+--------------+----------------------+ | tid | eventdate | title | timestamp | +------+----------------------+--------------+----------------------+ | 1 | 2008-03-15 18:00:00 | Konsertti | 2008-05-03 11:57:58 | | 2 | 2008-04-09 17:30:00 | Talkoopäivä | 2008-05-03 11:59:08 | | 3 | 2008-04-09 19:30:00 | Pullakahvit | 2008-05-03 11:59:32 | | 4 | 2008-08-29 08:00:00 | Rantaloma | 2008-05-03 12:00:09 | +------+----------------------+--------------+----------------------+
Nyt siis pitäisi saada aikaan tälle uudella formaatilla toimiva boksi, joka kertoo seuraavan tapahtuman nimen (tänään se siis olisi "Rantaloma"). Tämä olisi minulle helppoa, mutta kun taulussa voi olla samalle päivälle useampi tapahtuma. Miten näinä päivinä voisi aikajärjestyksessä näyttää tulevat tapahtumat seuraavalta tapahtumapäivältä? Siis huhtikuun 1. päivä kun katsoisi, näkisi
17:30 - Talkoopäivä 19:30 - Pullakahvit
Kellonajat osaan hakea ja kirjoitella itsekin, hakusessa on vain tapa hakea seuraava päivämäärä ja aikajärjestyksessä kaikki sinä päivänä tapahtuvat tapahtumat. Miten siis sellaisen haun voisi suorittaa?
Kiitos syvä.
Suunnilleen näin pitäisi onnistua:
SELECT eventdate.kello, title FROM tapahtumat WHERE eventdate.pvm IN ( SELECT eventdate.pvm FROM tapahtumat WHERE eventdate > NOW LIMIT 1 ) ORDER BY 1 ASC;
SQL vähän hakusessa, mutta tässä eventdate.kello tarkoittaa eventdatesta parsittua kellonaikaa ja eventdate.pvm päivämäärää (en muista miten se tehtiin, taisi jotenkin FORMAT-käskyllä tjms. saada).
EDIT: Ja ASC:n tilalle vissiin kuitenkin DESC, nyt ei aivot pelitä...Jompi kumpi kuitenkin.
Yksi vaihtoehto on hoitaa ihan PHP:n puolella sen kyselyn muodostaminen:
Paitsi että kyseessä ei ollut huominen vaan seuraava päivä jolloin on tapahtumia.
Aivan! Sisälukutaito kunniaan :) Eli siis unohtakaa tuo edellinen viestini... :)
Mikä siis toimisi käytännössä?
Tällainenkö?
SELECT eventdate, title FROM tapahtumat WHERE DATE_FORMAT(eventdate, '%Y-%m-%d') IN ( SELECT DATE_FORMAT(eventdate, '%Y-%m-%d') FROM tapahtumat WHERE eventdate > NOW LIMIT 1 ) ORDER BY 1 ASC;
Ihan toimivalta näyttää.
EDIT: Siis jos NOW antaa nykyhetken.
MySQL tarjoaa käyttöön myös muuttujat, joten voit ensin hakea lähimmän seuraavan tapahtuman ajankohdan ja vasta sitten sopivat tapahtumat, esimerkiksi siis näin:
SET @min_aika = (SELECT MIN(aika) FROM taulu WHERE aika > NOW()); SELECT * FROM taulu WHERE aika BETWEEN @min_aika AND (@min_aika + INTERVAL 1 DAY) ORDER BY aika;
Tällä kyselyllä saat seuraavasta tapahtumasta enintään vuorokauden päässä olevat tapahtumat. En jaksanut nyt niin tarkkaan lukea, että tietäisin, mitä aivan täsmälleen haluat saada, mutta kysy lisää, jos ei tällä selviä. :)
Minulle tuli tuollaisesta alikyselyä käyttävästä ratkaisusta tällainen virheilmoitus:
ERROR 1137 (HY000): Can't reopen table: 'taulu'
Siis tarkoitus oli saada seuraava tapahtumapäivä.
Jos tänään olisi 3.5., 4.5. ei tapahdu mitään ja aikajärjestyksessä seuraavat kaksi tapahtumaa ovat molemmat 13.5., pitäisi ne ja vain ne tapahtumat saada käsiteltäviksi.
Ja tuo kirjoittamani kysely ei toimi. mysql_fetch_array(): supplied argument is not a valid MySQL result resource
.
Käytä virheen selvittämiseen mysql_error-funktiota.
Tekemäni kyselyn pitäisi vastata tarpeitasi, kunhan pyöristät NOW-arvon ylös seuraavaan keskiyöhön, jotta tarkistus alkaisi seuraavasta päivästä, ja saadun min_aika-arvon vastaavasti alaspäin, jotta tulokset olisivat kaikki samalta päivältä.
mysql_error
tuotti sen saman minkä aina: "You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '; SELECT * FROM kalenteri WHERE eventdate BETWEEN @min_aika AND (@min_aika + IN' at line 1
".
Miten pyöristän nuo arvot?
Eikö näin onnistuisi?
<?php $sql = "SELECT DATE_FORMAT(eventdate, '%Y-%m-%D') FROM kalenteri WHERE eventdate > NOW() LIMIT 1"; $seuraavapvm = mysql_result( mysql_query($sql, $link), 0, 0 ); $sql = "SELECT eventdate, title FROM kalenteri WHERE DATE_FORMAT(eventdate, '%Y-%m-%d') = $seuraavapvm ORDER BY eventdate"; // ... ?>
Testaamatonta toki.
TsaTsaTsaan koodi on oikeilla jäljillä, mutta hakee tämän päivän tapahtumat, jos tapahtuman kellonaika ei ole vielä kulunut umpeen - en tiedä onko tarkoituksenmukaista? Lisäksi ekaan kyselyyn laittaisin ORDER BY eventdate ja jälkimmäiseen kyselyyn hipsut $seuraavapvm-muuttujan ympärille.
Tässä vielä omat versioni kyselyistä:
<?php // Haetaan seuraavan tapahtuman päivämäärä (kuluvan päivän tapahtumat suljettu laskuista pois) $nextDate = $db->get_value(" SELECT DATE_FORMAT(eventdate, '%Y-%m-%d') AS pvm FROM tapahtumat HAVING pvm > DATE_FORMAT(NOW(), '%Y-%m-%d') ORDER BY eventdate LIMIT 1"); //Haetaan ko. päivämäärän tapahtumat $results = $db->get_all(" SELECT eventdate, title FROM tapahtumat WHERE DATE_FORMAT(eventdate, '%Y-%m-%d') = '".$nextDate."' ORDER BY eventdate"); ?>
Edit: Tämä ei ehkä ole optimaalisin tapa, mutta jos tapahtumia ei ole kovin paljon, niin käytännössä haun optimoinnilla ei ole mitään merkitystä.
Hmm, mikäs tuo $db
on?
Se on kuvitteellinen tietokantaluokka, koska en jaksanut kirjottaa noita rivienhakurutiineja "oikeaoppisesti" tarkistuksineen tuohon. Otat tosta vaan nuo kyselyt ja loput sovellat itse.
Aihe on jo aika vanha, joten et voi enää vastata siihen.