Versio

Per record vier records uit andere tabel

Overzicht Reageren

Herjan -

Herjan -

23/02/2008 14:01:00
Quote Anchor link
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?
Gewijzigd op 01/01/1970 01:00:00 door Herjan -
 
PHP hulp

PHP hulp

25/05/2012 09:57:44
Gesponsorde koppelingen:
BHosted Hosting al vanaf € 1,- per maand

Controleer nu gratis jouw domeinnaam:

  
 
Thijs X

Thijs X

23/02/2008 14:06:00
Quote Anchor link
Ik denk niet dat dat mogelijk is in 1 query, omdat je eigenlijk een 2D array zou terug moeten krijgen ( Voor elke map max 4 afbeelding ).
 
Joren de Wit
Beheerder

Joren de Wit

23/02/2008 14:09:00
Quote Anchor link
Dit zijn verschillende vragen dus zul je ook verschillende queries nodig hebben. En om alle mappen op te halen en vervolgens om per map 4 foto's op te halen...

Uiteraard is het wel mogelijk in enkel SQL, maar dan zul je gebruik moeten maken van stored procedures om het gewenste resultaat uit de query te krijgen...
 
Frank -

Frank -

23/02/2008 14:09:00
Quote Anchor link
Dubbele records mogen niet voorkomen, dan is jouw datamodel niet goed.

Verder klinkt het alsof je een subquery nodig hebt, maar daar kun je in MySQL geen LIMIT op gebuiken. Ik vermoed dat je per map een aparte query nodig hebt om 4 willekeurige foto's op te halen.

Maar geef je datamodel eens, dan kunnen we echt meedenken.

Edit: Een stored procedure kan ook, maar die voert in feite ook aparte queries uit. Het grote voordeel is alleen dat je geen interactie tussen PHP en de database nodig hebt, het gaat dus sneller.
Gewijzigd op 01/01/1970 01:00:00 door Frank -
 
Herjan -

Herjan -

23/02/2008 14:27:00
Quote Anchor link
pgFrank schreef op 23.02.2008 14:09:
Dubbele records mogen niet voorkomen, dan is jouw datamodel niet goed.


Sorry, zat idd een kromme zin in mijn post. Moet zijn:

Quote:
...dat er geen records dubbel geselecteerd mogen worden?


Datamodel met wat data erin:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
-- Zie de structuur een aantal posts verderop --
Gewijzigd op 01/01/1970 01:00:00 door Herjan -
 
Frank -

Frank -

23/02/2008 14:29:00
Quote Anchor link
MyISAM... Daarmee is geen relationele database te maken, ga de boel eerst maar eens omzetten naar innoDB en de foreign keys inbouwen.
 
Steff   an

Steff an

23/02/2008 14:40:00
Quote Anchor link
pgFrank mag ik vragen of dat voor dit probleem IETS uit maakt? Het is leuk dat je hem probeert te helpen, maar hij vraagt hier toch niet om.
Gewijzigd op 01/01/1970 01:00:00 door Steff an
 
Frank -

Frank -

23/02/2008 14:43:00
Quote Anchor link
Steffan schreef op 23.02.2008 14:40:
maar hij vraagt hier toch niet om.
En is dat een reden om iemand maar van de wal in de sloot te helpen? Voor mij in elk geval niet.

Zorg eerst voor een goede basis, een goed datamodel met de juiste relaties, en ga je dan pas druk maken over het ophalen van de data. Data moet in de eerste plaats betrouwbaar zijn, of niet dan?
 
Joren de Wit
Beheerder

Joren de Wit

23/02/2008 14:44:00
Quote Anchor link
@Steffan: Dat maakt voor dit probleem heel veel uit! Er wordt namelijk bij het selecteren van de records uitgegaan van relaties tussen tabellen die helemaal niet bestaan. Met andere woorden, je weet nooit of de data die je terug krijgt wel betrouwbaar is!

Bovendien bestaat het helpen van iemand niet altijd uit het enkel antwoord geven op de gestelde vraag, maar soms ook uit het aanwijzen van grotere problemen en daar een oplossing voor geven. Je kunt nu wel de oplossing op het gestelde probleem geven, maar daar heeft de TS niets aan als zijn database straks op z'n gat ligt.
 
Steff   an

Steff an

23/02/2008 14:55:00
Quote Anchor link
True,true.. Maaaar nu verwacht ik ook antwoord op zijn vraag natuurlijk :)
 
Joren de Wit
Beheerder

Joren de Wit

23/02/2008 15:00:00
Quote Anchor link
Steffan schreef op 23.02.2008 14:55:
True,true.. Maaaar nu verwacht ik ook antwoord op zijn vraag natuurlijk :)
Het lijkt me dat dat in post 2-4 van dit topic al gegeven is: nee, het kan waarschijnlijk niet in 1 query. En aan de hand van het datamodel wordt vervolgens de suggestie gegeven om dat eerst eens aan te passen, aangezien dat zeker problemen gaat geven...

Ik snap je punt dus niet echt.
 
Steff   an

Steff an

23/02/2008 15:04:00
Quote Anchor link
@Blanche.. ik ook niet helemaal :P

Heb die posts nooit gezien.. mijn fout! Ik oordeelde (weer) eens te snel.
Gewijzigd op 01/01/1970 01:00:00 door Steff an
 
Herjan -

Herjan -

23/02/2008 15:09:00
Quote Anchor link
Ok, heb het nu omgezet naar InnoDB en twee foreign keys aangebracht.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
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
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
--
-- 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;
 
Herjan -

Herjan -

23/02/2008 15:09:00
Quote Anchor link
Edit:
Dubbelpost :S Wanneer komt de nieuwe versie nou? We zitten al een maand over de deadline. ICT-project ofzo? :P
Gewijzigd op 01/01/1970 01:00:00 door Herjan -
 
Joren de Wit
Beheerder

Joren de Wit

23/02/2008 15:17:00
Quote Anchor link
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.
 
Frank -

Frank -

23/02/2008 15:29:00
Quote Anchor link
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.
 
Herjan -

Herjan -

23/02/2008 16:47:00
Quote Anchor link
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:

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
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.
 
Joren de Wit
Beheerder

Joren de Wit

23/02/2008 16:52:00
Quote Anchor link
Quote:
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 ;-)
 
Herjan -

Herjan -

24/02/2008 19:40:00
Quote Anchor link
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.
Gewijzigd op 01/01/1970 01:00:00 door Herjan -
 
Joren de Wit
Beheerder

Joren de Wit

24/02/2008 19:44:00
Quote Anchor link
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...
 
Herjan -

Herjan -

24/02/2008 21:44:00
Quote Anchor link
Helaas, dan doen we het maar zo.
 



Overzicht Reageren