JOIN query met teveel results

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Dennis WhoCares

Dennis WhoCares

09/04/2016 20:22:30
Quote Anchor link
Hi all,

zoals jullie al eerder waarschijnlijk vernomen hebben is mijn huidig project een ticket systeem.
Hierbij heb ik een one-to-many relatie vanaf ticket tabel, en media tabel.

dmv. een JOIN query ben ik een overzicht aan het maken, waarbij ik maar 1 resultaat (eerste) van de media tabel wil.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
SELECT t.*,m.media_path FROM tickets t JOIN media ON t.ticket_id = media_ticket_id ORDER BY t.ticket_date DESC LIMIT 0,20


Hiermee wil ik dus de laatste 20 tickets weergeven en wil ik het path weten van de eerste media file die erbij hoort.
Helaas krijg ik nu voor de laatste ticket al 5 resultaten, omdat er 5 bestanden aan gelinked zijn.

Hoe kan ik de JOIN ook limiteren tot 1 resultaat ?
 
PHP hulp

PHP hulp

16/11/2024 02:55:06
 
Thomas van den Heuvel

Thomas van den Heuvel

09/04/2016 20:47:30
Quote Anchor link
Een LEFT JOIN gebruiken en groeperen op ticket id? Dan is het niet noodzakelijk om media-attachments bij een ticket te hebben voor het vinden van een ticket - of is dit altijd verplicht (is er altijd ten minste één media bestand gekoppeld aan het ticket)?

Mogelijk kun je iets met MIN(<media id>) ofzo doen om het eerste media bestand te vinden (indien aanwezig)? Je zou ook kunnen overwegen om het media id redundant bij het ticket op te slaan.
 
Dennis WhoCares

Dennis WhoCares

09/04/2016 20:52:38
Quote Anchor link
Ach.. lomp he.. group by did the trick..

In principe is er bij elke ticket ten alle tijden minimaal 1 media item beschikbaar, het zij een screenshot, video, document.
De media table bevat de paden naar deze media incl een thumbnail/preview ervan.

Thanks Thomas!
 
Ivo P

Ivo P

09/04/2016 21:12:27
Quote Anchor link
eh

"group by did the trick" klinkt een beetje als: "ik heb group by in de query gefrommeld en op het eerste oog krijg ik de data die ik wil" en dan zonder begrip van wat group by doet.

Group by hoort in een query thuis waar aggregatie functies staan.
Standaard staat de error reporting van Mysql laag mbt het foutief gebruik van group-by.
Met gevolg dat Mysql iets doet dat mogelijk is wat je wilt hebben. Of niet, of niet altijd. Dat is af te wachten.

http://wiki.pfz.nl/group-by

Achter GROUP BY horen alle kolommen te volgen die in SELECT ook staan, met uitzondering van de aggregatie functies als MIN(), MAX(), COUNT() etc.

Doe je dat niet, dan trekt mysql zijn eigen plan en levert je voor de niet genoemde kolommen willekeurige waarden aan.
 
Dennis WhoCares

Dennis WhoCares

09/04/2016 21:16:01
Quote Anchor link
Ivo P op 09/04/2016 21:12:27:
"group by did the trick" klinkt een beetje als: "ik heb group by in de query gefrommeld en op het eerste oog krijg ik de data die ik wil" en dan zonder begrip van wat group by doet.

Ehm eerlijk? Ja inderdaad :D
Ik zal is ff die link bekijken

Ivo P op 09/04/2016 21:12:27:
Achter GROUP BY horen alle kolommen te volgen die in SELECT ook staan, met uitzondering van de aggregatie functies als MIN(), MAX(), COUNT() etc.

Doe je dat niet, dan trekt mysql zijn eigen plan en levert je voor de niet genoemde kolommen willekeurige waarden aan.

Maar group by ticket_id, geeft ie dan niet gewoon slechts de waardes in de 'result' van die ene ticket weer? Het lijkt er niet op dat ik willekeurige tickets krijg met de preview van daarbij horende media, in de link gaat het ook maar over 1 GROUP BY field.

Zou in principe nog een MIN(m.media_id) kunnen doen, dan weet ik zeker dat ik de eerste media erbij krijg
Gewijzigd op 09/04/2016 21:17:24 door Dennis WhoCares
 
Ivo P

Ivo P

09/04/2016 21:47:11
Quote Anchor link
SELECT a.ticktet_id, b.media_id
FROM tabel a
JOIN tabel2 b ON ...
GROUP BY a.ticket_id

als je dit doet, krijg je *een* media_id

Maar welke zal een verrassing blijven.
mogelijk die met de laagste primary key, maar misschien verandert dat weer als de records op een andere volgorde komen te staan.

Een query moet altijd eenduidig zijn.
Stel bijvoorkeur ook je database zo in dat hij niet in de vergevingsmode staat en maar wat doet.
 
Dennis WhoCares

Dennis WhoCares

09/04/2016 22:03:43
Quote Anchor link
Ivo P op 09/04/2016 21:47:11:
SELECT a.ticktet_id, b.media_id
FROM tabel a
JOIN tabel2 b ON ...
GROUP BY a.ticket_id

als je dit doet, krijg je *een* media_id

Maar welke zal een verrassing blijven.
mogelijk die met de laagste primary key, maar misschien verandert dat weer als de records op een andere volgorde komen te staan.

Een query moet altijd eenduidig zijn.
Stel bijvoorkeur ook je database zo in dat hij niet in de vergevingsmode staat en maar wat doet.



Je hebt absoluut gelijk. Hoe kan ik ervoor zorgen dat die ene media id die bij ticket id hoort, daadwerkelijk de eerste media id van die ticket is?
Is de enige optie dan om deze eerste media id te benoemen in de ticket record?
 
Ivo P

Ivo P

09/04/2016 22:08:53
Quote Anchor link
met MIN() moet je het ook lukken.

En dan alle andere kolommen in group by,

Zitten er nog meer waarden bij die dubbel voorkomen?

SELECT met *
en group-by is nooit een fijne combi.

Geef gewoon alle kolommen op
Dan heb je ook de zekerheid dat je group by klopt.

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
SELECT t.ticket_id, t.foo, t.bar, t.ticket_date
       MIN(m.media_path)
FROM tickets t
JOIN media ON t.ticket_id = media_ticket_id
GROUP BY t.ticket_id, t.foo, t.bar, t.ticket_date
ORDER BY t.ticket_date
DESC LIMIT 0,20
 
Jan de Laet

Jan de Laet

10/04/2016 08:05:16
Quote Anchor link
@Dennis,
wat is "daadwerkelijk de eerste media id"?...
Is dat die met het laagste id, oudste datum, of media_path zoals Ivo gebruikt.
 
Dennis WhoCares

Dennis WhoCares

10/04/2016 09:00:03
Quote Anchor link
Thanks Ivo,
ik ga eens spelen met MIN(m.media_id) en MAX(m.media_id) of ik dan daadwerkelijk de eerste en laatste media krijg.
De reden van t.* is omdat er enorm veel velden in staan

@Jan, de eerste media van de ticket is inderdaad met de laagste id :)

Komt goed! Thanks guys
 
Jan de Laet

Jan de Laet

10/04/2016 09:44:24
Quote Anchor link
Ik zou dit zelf met een subquery doen waarin je eerste media bepaalt per ticket:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
SELECT media_ticket_id, MIN(id)
FROM media
GROUP BY media_ticket_id


Dit resultaat kun je als subquery bij je join gebruiken.
Met de 2e join heb je toegang tot alle kolommen uit media tabel.
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
SELECT t.*, m1.id, m.media_path
FROM tickets t
LEFT OUTER JOIN (
    SELECT media_ticket_id, MIN(id) as id
    FROM media
    GROUP BY media_ticket_id) m1 ON m1.media_ticket_id = t.id
LEFT OUTER JOIN media m ON m.id = m1.id
Gewijzigd op 10/04/2016 20:39:05 door Jan de Laet
 
Thomas van den Heuvel

Thomas van den Heuvel

10/04/2016 16:03:50
Quote Anchor link
Thomas van den Heuvel op 09/04/2016 20:47:30:
Mogelijk kun je iets met MIN(<media id>) ofzo doen om het eerste media bestand te vinden (indien aanwezig)? Je zou ook kunnen overwegen om het media id redundant bij het ticket op te slaan.

Ik zie eigenlijk weinig nieuwe informatie, enkel aanvullende.
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.