[PHP / MySQL] Snellere manier hiervoor?

Pagina: 1
Acties:

Onderwerpen


Verwijderd

Topicstarter
Ik heb een klein scriptje waaruit informatie gehaald wordt uit verschillende MySQL tabellen. In de eerste tabel staan plaatjes, en dan moet hij een lijst maken met de meest recent geupdate albums. De namen van de albums staan in een andere tabel, dus dit heb ik opgelost via een joined mysql_query (heet het zo?). Als ik dan in een bepaald album op een dag tien plaatjes erbij zet, dan moet hij echter niet tien keer dat album neerzetten, maar gewoon 1 keer, en dan een lijstje met de volgende 8 geupdate albums.
Dit wilde ik oplossen met een DISTINCT erbij, maar dan krijg je een heel andere volgorde. Nu heb ik het op de volgende manier opgelost, maar er moet toch een betere manier zijn?

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
$cat == "" ? $filter = "" : $filter = "AND B.category = $cat";
$i = 0;

$sql = mysql_query("SELECT B.id, B.name, B.album, C.abbreviation FROM vg_files A, vg_games B, vg_categories C WHERE B.album = A.album $filter AND C.id = B.category AND A.type = 'video' ORDER BY A.id DESC", $dbh);
while ($row = mysql_fetch_array($sql) AND $i < 9)
    {
    if ($row[album] != $temp_album)
        {
        echo'
        <a href="/'. $row[abbreviation] .'/videos/'. $row[id] .'/'. $row[name] .'/" class="rightgame">'. $row[name] .'</a>
        ';
        
        $temp_album = $row[album];
        $i++;
        }
    }


Zoals je ziet gaat hij nu steeds al die plaatjes langs en checkt dan of het album niet gelijk is aan het vorige album. Dit gaat door totdat de $i variabele 9 heeft bereikt. Niet echt de meest ideale oplossing dacht ik zo, maar GROUP BY en DISTINCT leveren heel andere lijsten op. Heeft iemand een idee hoe dit op te lossen is?

(btw, sorry voor de nogal onduidelijk titel, maar ik heb geen idee hoe ik dit probleempje moet noemen...)

  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
Voor zover ik kan zien is dit puur een database-probleem...?

Kan je misschien de tabelstructuren van de tabellen vg_files, vg_games en vg_categories posten, samen met wat voorbeeld-data? Anders wordt het voor ons behoorlijk lastig om uit te vinden wat er nu precies niet goed gaat.

[ Voor 20% gewijzigd door MrBucket op 20-09-2006 20:45 ]


Verwijderd

Gewoon group by B.album??

Kun je misschien in het kort je tabelstructuur even toelichten? In vg_files staan je images (waarom dan type='video' :? ), in vg_games je albums en vg_categories de categorieen of zo?

Dit is geen joined mysql_query, ook geen idee wat dat is :) Gewoon een vrij simpele query.

Zie ook Programming FAQ - SQL en Programming FAQ - SQL ...

[ Voor 19% gewijzigd door Verwijderd op 20-09-2006 20:46 ]


Verwijderd

Topicstarter
type = video omdat ik twee lijsten heb (eentje voor plaatjes en eentje voor video), die allebei in dezelfde tabel staan. Hieronder de info van de tabbelen:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
CREATE TABLE `vg_files` (
  `id` int(11) NOT NULL auto_increment,
  `name` text NOT NULL,
  `file` text NOT NULL,
  `album` text NOT NULL,
  `type` text NOT NULL,
  `timestamp` bigint(14) NOT NULL default '0',
  `size` text NOT NULL,
  `description` text NOT NULL,
  `splash` text NOT NULL,
  `url` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=13830 ;

CREATE TABLE `vg_games` (
  `id` int(11) NOT NULL auto_increment,
  `name` text NOT NULL,
  `category` text NOT NULL,
  `image` text NOT NULL,
  `album` text NOT NULL,
  `developer` text NOT NULL,
  `publisher` text NOT NULL,
  `genre` text NOT NULL,
  `release_date` bigint(14) NOT NULL default '0',
  `views` int(16) NOT NULL default '0',
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=699 ;


De categorie tabel heeft er weinig mee te maken denk, maar hieronder toch even de info:

PHP:
1
2
3
4
5
6
7
8
9
CREATE TABLE `vg_categories` (
  `id` int(11) NOT NULL auto_increment,
  `name` text NOT NULL,
  `image` text NOT NULL,
  `template` text NOT NULL,
  `view_lvl` text NOT NULL,
  `abbreviation` text NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 AUTO_INCREMENT=15 ;


In vg_files staan de bestanden opgeslagen, samen met het id nummer van het album. Vervolgens pakt hij de naam van de game uit vg_games (daar staat ook dat albumnummer in, dus die pakt ie dan samen daarop). In vg_categories pakt ie vervolgens weer de naam van de category waar de game bijhoort, aangezien deze in de url moet komen te staan.

(ik vond het al aardig moeilijk worden, aangezien dit de eerste website is waarin ik scripts gebruik om info uit meerdere tabbelen tegelijk te krijgen :P )

[ Voor 4% gewijzigd door Verwijderd op 20-09-2006 21:12 ]


Verwijderd

In vg_files staan de bestanden opgeslagen, samen met het id nummer van het album. Vervolgens pakt hij de naam van de game uit vg_games (daar staat ook dat albumnummer in, dus die pakt ie dan samen daarop). In vg_categories pakt ie vervolgens weer de naam van de category waar de game bijhoort, aangezien deze in de url moet komen te staan.
Ik heb het 3x gelezen maar snap het nog steeds niet. Wat zijn hier bestanden? En albums? En wat hebben games hier mee te maken :?.

Dat je dingen in twee tabellen opslaat en dat samen pakt daarop klinkt mij niet echt lekker in de oren...

Ik denk dat je eerst even goed moet nadenken wat je doet en vervolgens gaat programmeren. Heb het idee dat je beetje zit te hacken en dat het na een half uur hacken nog niet wil en je door de bomen het bos niet meer ziet :+ (zo heb ik ook wel eens queries proberen te maken namelijk :) ).

En met een omschrijving van de tabellen + velden bedoelde ik (en de andere poster) denk ik niet de SQL-code van het createn :X Wat voorbeelddata is ook wel handig denk ik, zo komen we niet echt verder.

[ Voor 9% gewijzigd door Verwijderd op 20-09-2006 21:23 ]


  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Nofi, maar je mist blijkbaar de broodnodige kennis over een aantal basis (My)SQL keywords/features, zoals GROUP BY en LIMIT. De 1e is een mogelijke antwoord op deze specifieke vraag en de 2e is een goede verbetering aan huidige query. Nu limiteer je het aantal resultaten in de code (dmv $i < 9), maar dat kan met LIMIT al op database niveau gedaan worden, wat scheelt in querytijden en in de hoeveelheid verkeer tussen db en applicatie. :)
C.id = B.category
Ho, iets een nummertje als primary key heeft en je wilt daar naar verwijzen, definieer die kolom dan gewoon met hetzelfde datatype. Al je foreign keys (google term!) zijn text velden terwijl ze int(11) hadden moeten zijn. Verder zijn heel veel kolommen text terwijl (var)char zou volstaan. Lees dus ook even wat meer over de verschillende datatypes in de MySQL manual.

[ Voor 30% gewijzigd door Voutloos op 20-09-2006 21:39 ]

{signature}


Verwijderd

Topicstarter
Voutloos schreef op woensdag 20 september 2006 @ 21:31:
Nofi, maar je mist blijkbaar de broodnodige kennis over een aantal basis (My)SQL keywords/features, zoals GROUP BY en LIMIT. De 1e is een mogelijke antwoord op deze specifieke vraag en de 2e is een goede verbetering aan huidige query. Nu limiteer je het aantal resultaten in de code (dmv $i < 9), maar dat kan met LIMIT al op database niveau gedaan worden, wat scheelt in querytijden en in de hoeveelheid verkeer tussen db en applicatie. :)
Dat is dus het probleem. Als ik er een GROUP BY B.album bijzet dan krijg je een heel andere (en verkeerde) lijst, daarom deed ik het op deze manier en vroeg ik me af of er geen betere was.

Ok, om alles wat duidelijker te maken, hieronder een versimpelde versie:

PHP:
1
2
3
4
5
$sql = mysql_query("SELECT B.id, B.name, B.album FROM vg_files A, vg_games B WHERE B.album = A.album ORDER BY A.id DESC LIMIT 0,10", $dbh);
while ($row = mysql_fetch_array($sql))
    {
    echo $row[name];
    }

Dan krijg je dus een lijst met de laaste rijen uit vg_files, dus zoiets (het gaat om screenshots en videobestanden van videogames):

GTA3
GTA3
GTA3
Saints Row
Saints Row
Viva Pinata
Viva Pinata
GTA3
GTA3

Nu wil ik het zo hebben dat hij die lijst samenvoegt tot:

GTA3
Saints Row
Viva Pinata
GTA3

Dus geen dubbele achter elkaar. Dit probeerde ik door een GROUP BY toe te voegen, zoals deze:


PHP:
1
2
3
4
5
$sql = mysql_query("SELECT B.id, B.name, B.album FROM vg_files A, vg_games B WHERE B.album = A.album GROUP BY A.album ORDER BY A.id DESC LIMIT 0,10", $dbh);
while ($row = mysql_fetch_array($sql))
    {
    echo $row[name];
    }

Dan krijg je echter een heel andere lijst, dus niet op de goede volgorde.

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Joins kan je beter ook uitvoeren met 'ON' of 'USING' erbij om aan te geven waarop gejoined moet worden.

offtopic:
En $sql is een slechte variabelenaam, want de waarde van de variabele is helemaal geen SQL, maar een resource/resultset. ;)
Verwijderd schreef op woensdag 20 september 2006 @ 21:44:
GTA3
Saints Row
Viva Pinata
GTA3
Dus geen dubbele achter elkaar. Dit probeerde ik door een GROUP BY toe te voegen, zoals deze:
[...]
Dan krijg je echter een heel andere lijst, dus niet op de goede volgorde.
Ik ga niet raden waarom GTA3 wel 2x in dat lijstje moet staan, danwel welke volgorde anders dan a.id DESC die laatste query er op magische wijze uitgetoverd krijgt.

Verwerk eerst maar de reeds gegeven hints en probeer het dan nog eens. :)

{signature}


Verwijderd

Zoals al eerder verteld moet je hiervoor met DISTINCT werken.
Met een beetje googlen kom je er dan wel uit.

linkje

Verwijderd

Dan krijg je echter een heel andere lijst, dus niet op de goede volgorde.
Wat krijg je dan??

Hoeft niet per se met DISTINCT, group by is bij meerdere velden veel handiger en levert dan, als je het goed doet, het gewenste resultaat.

En idd, waarom moet GTA3 er 2x in staan :?

Succes...

[ Voor 29% gewijzigd door Verwijderd op 20-09-2006 23:27 ]

Pagina: 1