Een iets ingewikkelder MySQL-vraagje vandaag. Ik ben bezig aan een fotoalbum en ik wil graag, net als in Windows Explorer, dat je bij een map alvast vier kleine foto'tjes ziet uit die map.

Op het moment haal ik met één query alle mappen op. Dat zou ik graag zo willen houden, in verband met de snelheid. Is het mogelijk om in die ene query gelijk vier willekeurige foto's te selecteren uit een andere tabel?

In de tabel met foto's wordt het id van de map waar de foto in staat opgeslagen. Op die manier is een foto te herkennen als in een bepaalde map horende.

Is dit mogelijk met MySQL? En ook rekening houdend met het feit dat niet in alle mappen vier foto's zitten en dat er geen records dubbel geselecteerd mogen worden?
@Blanche.. ik ook niet helemaal :P

Heb die posts nooit gezien.. mijn fout! Ik oordeelde (weer) eens te snel.
Ok, heb het nu omgezet naar InnoDB en twee foreign keys aangebracht.

--
-- Tabel structuur voor tabel 'foto_albums'
--

CREATE TABLE IF NOT EXISTS foto_albums (
  falbum_id int(10) NOT NULL auto_increment,
  falbum_parent int(10) default NULL,
  falbum_title varchar(255) NOT NULL,
  falbum_created datetime NOT NULL,
  falbum_edited datetime default NULL,
  falbum_level tinyint(1) NOT NULL default '1',
  falbum_deleted tinyint(1) NOT NULL default '0',
  PRIMARY KEY  (falbum_id),
  KEY falbum_parent (falbum_parent)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ;

--
-- Gegevens worden uitgevoerd voor tabel 'foto_albums'
--

INSERT INTO foto_albums (falbum_id, falbum_parent, falbum_title, falbum_created, falbum_edited, falbum_level, falbum_deleted) VALUES
(2, NULL, 'Vakantie', '2008-02-23 14:59:34', NULL, 1, 0),
(3, NULL, 'Auto''s', '2008-02-23 14:59:34', NULL, 1, 0),
(4, 2, 'Dag 1', '2008-02-23 15:00:08', NULL, 1, 0),
(5, 2, 'Dag 2', '2008-02-23 15:00:08', NULL, 1, 0),
(6, 2, 'Dag 3', '2008-02-23 15:00:29', NULL, 1, 0),
(7, 3, 'Porsche', '2008-02-23 15:00:29', NULL, 1, 0),
(8, 3, 'Hummer', '2008-02-23 15:00:40', NULL, 1, 0);

-- --------------------------------------------------------

--
-- Tabel structuur voor tabel 'foto_fotos'
--

CREATE TABLE IF NOT EXISTS foto_fotos (
  ffoto_id int(10) NOT NULL auto_increment,
  falbum_id int(10) default NULL,
  ffoto_title varchar(255) NOT NULL,
  ffoto_desc varchar(1000) default NULL,
  ffoto_views int(10) NOT NULL default '0',
  ffoto_added datetime NOT NULL,
  ffoto_deleted tinyint(1) NOT NULL default '0',
  ffoto_level tinyint(1) NOT NULL default '1',
  PRIMARY KEY  (ffoto_id),
  KEY falbum_parent (falbum_id)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ;

--
-- Gegevens worden uitgevoerd voor tabel 'foto_fotos'
--

INSERT INTO foto_fotos (ffoto_id, falbum_id, ffoto_title, ffoto_desc, ffoto_views, ffoto_added, ffoto_deleted, ffoto_level) VALUES
(1, 4, 'IMG_1902.JPG', NULL, 0, '2008-02-23 15:02:09', 0, 1),
(2, 4, 'IMG_1845.JPG', NULL, 0, '2008-02-23 15:02:21', 0, 1),
(3, 4, 'IMG_1846.JPG', NULL, 0, '2008-02-23 15:02:34', 0, 1),
(4, 4, 'IMG_1848.JPG', NULL, 0, '2008-02-23 15:02:47', 0, 1),
(5, 4, 'IMG_1856.JPG', NULL, 0, '2008-02-23 15:03:00', 0, 1),
(6, 4, 'IMG_1869.JPG', NULL, 0, '2008-02-23 15:03:15', 0, 1),
(7, 4, 'IMG_1891.JPG', NULL, 0, '2008-02-23 15:03:28', 0, 1);

--
-- Beperkingen voor gedumpte tabellen
--

--
-- Beperkingen voor tabel `foto_albums`
--
ALTER TABLE `foto_albums`
  ADD CONSTRAINT foto_albums_ibfk_1 FOREIGN KEY (falbum_parent) REFERENCES foto_albums (falbum_id) ON DELETE SET NULL ON UPDATE CASCADE;

--
-- Beperkingen voor tabel `foto_fotos`
--
ALTER TABLE `foto_fotos`
  ADD CONSTRAINT foto_fotos_ibfk_1 FOREIGN KEY (falbum_id) REFERENCES foto_albums (falbum_id) ON DELETE SET NULL ON UPDATE CASCADE;
[edit]Dubbelpost :S Wanneer komt de nieuwe versie nou? We zitten al een maand over de deadline. ICT-project ofzo? :P[/edit]
Ok, ziet er al beter uit. Nu kun je dus de queries gaan opstellen die je nodig hebt, dus 1 voor het ophalen van alle albums en vervolgens per album nog 1 om de 4 foto's op te halen.
ON DELETE SET NULL
Weet je heel zeker dat dit goed is? Meestal is RESTRICT beter, dan wordt je gedwongen om eerst de gekoppelde records van juiste data te voorzien en dán pas kun je de bron verwijderen. Nu blijf je mogelijk met een enorme bak ellende zitten die geen enkel verband meer heeft met andere data.
Blanche schreef op 23.02.2008 15:17
Ok, ziet er al beter uit. Nu kun je dus de queries gaan opstellen die je nodig hebt, dus 1 voor het ophalen van alle albums en vervolgens per album nog 1 om de 4 foto's op te halen.
De albums ophalen heb ik al, dat zit netjes ingebakken in mijn class:

SELECT falbum_id, falbum_parent, falbum_title, falbum_level, falbum_deleted
FROM foto_albums
WHERE falbum_parent = ".$sqlalbumid."
ORDER BY falbum_created, falbum_id


De foto's is een kwestie van de goede WHERE opgeven om alleen uit het goede album te selecteren. Vervolgens een ORDER BY RAND() en LIMIT 4.

Mijn vraag was voornamelijk of het ook met één query mogelijk is. Maar dat lijkt niet te kunnen als ik jullie zo hoor.

pgFrank schreef op 23.02.2008 15:29
ON DELETE SET NULL
Weet je heel zeker dat dit goed is? Meestal is RESTRICT beter, dan wordt je gedwongen om eerst de gekoppelde records van juiste data te voorzien en dán pas kun je de bron verwijderen. Nu blijf je mogelijk met een enorme bak ellende zitten die geen enkel verband meer heeft met andere data.
Dat is even van later zorg. Ik ga daar naar kijken als ik ook met het beheren van het fotoalbum bezig ga, dan kan ik namelijk kijken wat ik doe bij het verwijderen van een album. Of ik dan alle foto's en albums daarin omhoog verplaats ofzo, of dat ik ze ook verwijder, of dat ik geen toestemming geef om te verwijderen als het album niet leeg is.
Dat is even van later zorg.
Tip: zet de ON UPDATE en ON DELETE dan zolang op RESTRICT. Op die manier kun je in de tussentijd niet per ongeluk de data uit de database verwijderen en zo de database slopen ;-)
Boem.[edit]Volgens mij kan het niet, maar zou het toch graag zeker weten :P Anders zit ik straks met een traag fotoalbum terwijl het ook veel sneller kan.[/edit]
Het zijn verschillende vragen die je stelt aan de database, daar heb je dus verschillende queries voor nodig. Dat is niet anders.

De enige manier waarop je het dan nog zou kunnen versnellen is bijvoorbeeld door deze verschillende queries in een stored procedure te verwerken waardoor er geen PHP meer aan te pas komt om alle benodigde gegevens op te halen.

Wellicht dat je er met een paar slim opgestelde subqueries ook wel uitkomt, maar dan nog zul je PHP nodig hebben om het resultaat van de query uit te pluizen. Als er in zo'n geval dan al snelheidswinst is, is dat waarschijnlijk minimaal...
Helaas, dan doen we het maar zo.

Reageren