Toon posts:

[MySQL] zoek query met meerdere joins

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik zit voor het moment met de handen in het haar, ik ben namelijk een zoek-query aan het opstellen maar het wil maar niet lukken...


Ik zit met de volgende tabellen:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
+--------------------+
| companies          |
+--------------------+
| companiesId        |
| companiesName      |
| companiesAddress   |
| ...                |
+--------------------+

+--------------------+
| keywords_companies |
+--------------------+
| keywordsId         |
| companiesId        |
+--------------------+

+--------------------+
| keywords           |
+--------------------+
| keywordsId         |
| keywordsName       |
| keywordsDescription|
+--------------------+

OPM: keywords_companies is dus een kruistabel (je kan je misschien afvragen waarom ik dit gedaan heb, maar dit is omdat keywords ook aan andere tabellen gelinked kunnen worden).

Ik zou nu een zoek-query willen opstellen die in alles gaat zoeken (dus zowel in de companies-tabel als in de gelinkte keywords), en de gevonden companies teruggeeft.

De query die ik op dit moment gebruik is:
code:
1
2
3
4
5
6
7
8
9
10
11
12
SELECT
*
FROM
companies c
LEFT JOIN keywords_companies kc ON c.companiesId=kc.companiesId
INNER JOIN keywords k ON k.keywordsId=kc.keywordsId
WHERE
((c.companiesName LIKE '%".$searchString."%')
OR
(c.companiesAddress LIKE '%".$searchString."%')
OR
(k.keywordsName LIKE '%".$searchString."%'))

Het probleem hiermee is echter dat met deze query de bedrijven dubbel, driedubbel,... worden teruggegeven. Dit komt doordat voor elk gelinkt keyword een volledige rij gejoined wordt, een voorbeeldje ervan:

COMPANIESID,COMPANIESNAME,COMPANIESADDRESS,KEYWORDSNAME
-----------------------------------------
(1,Microsoft,Silicon Valley,keyword1)
(1,Microsoft,Silicon Valley,keyword2)
(1,Microsoft,Silidon Valley,keyword3)
...

Als ik dan dus op 'eywor' gezocht wordt, krijg ik Microsoft 3x in mijn resultatentabel terwijl ik het er maar 1x in zou willen hebben.

Heeft er iemand een idee hoe ik dit het best kan oplossen?

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Je hebt twee keer een inner join nodig lijkt me. :) In plaats van een inner en een left dus.

[ Voor 34% gewijzigd door NMe op 16-06-2005 21:38 ]

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • Lukse
  • Registratie: Januari 2004
  • Laatst online: 12-04-2023
Doe eens een SELECT DISTINCT companiesname FROM...

Verwijderd

Topicstarter
Ik heb eens uitgetest, maar nog steeds hetzelfde probleem...

Misschien dat ik mijn probleem een beetje uitgebreider moet omschrijven:

Ik heb dus een tabel met daarin allemaal gevens over bedrijven. Aan ieder bedrijf kunnen meerdere "keywords" gelinkt worden. Deze "keywords" zitten een andere tabel en worden dmv een kruistabel gelinkt aan een bedrijf gelinkt. De reden hiervoor is dus zoals ik reeds in mijn openingspost vermeld heb dat deze "keywords" ook aan andere tabellen gelinkt worden (waarvoor dan een andere kruistabel aangemaakt wordt).

Nu wil ik dus een zoekfunctie maken die in ALLE gegevens over een bepaald bedrijf zoekt, dus zowel in de tabel 'companies' als in de gelinkte "keywords".


vb. ik heb een bedrijf met id='1', companiesName='RedHat' en de keywords 'linux', 'open source', 'fedora' en 'operating system' eraan gelinkt. Stel nu dat ik de zoek op de string 'pe'. Deze string komt zowel voor in het keyword 'oPEn source' als 'oPErating system'.

Een query, zoals ikzelf eigenlijk in gedachten had, die ik dus niet kan gebruiken is de volgende:
code:
1
2
3
4
5
6
7
8
9
10
SELECT
*
FROM
companies c
INNER JOIN keywords_companies kc ON c.companiesId=kc.keywordsId
INNER JOIN keywords k ON kc.keywordsId=k.keywordsId
WHERE
c.companiesName LIKE '%op%'
OR
k.keywordsName LIKE '%op%'

Want deze query zou als resultaat de volgende rows geven:
row1: '1','RedHat','open source'
row2: '1','RedHat','operating system'
En ik zou dus eingelijk maar één enkele row al resultaat willen hebben...


Nu dat ik dit alles allemaal aan het opschrijven ben bedenk ik mij juist dat ik misschien gewoon met een subquery moet werken, ik gebruik dan als het ware eerst de query van hierboven waarop ik dan een query uitvoer die daar 'distinct' alle companiesNames uithaalt. Maar ik heb eigenlijk nog nooit met subqueries gewerkt. Kan iemand mij vertellen of dit een mogelijk juiste oplossing zou zijn?


edit:

@Lukske
Dit zou inderdaad wel eens een oplossing kunnen zijn, ik ga het dadelijk eens uittesten!

[ Voor 11% gewijzigd door Verwijderd op 16-06-2005 22:04 . Reden: reply added ]


  • NMe
  • Registratie: Februari 2004
  • Laatst online: 15-04 22:07

NMe

Quia Ego Sic Dico.

Ah, je wil alleen de companies hebben? Dan heb je inderdaad een SELECT DISTINCT nodig. Als je wel alle velden nodig hebt, dan zul je het daar ook niet mee redden, en zul je een GROUP BY in elkaar moeten knutselen. Daarbij moet je je dan wel afvragen op welke velden je groepeert, welke velden je nodig hebt en hoe je dat gaat doen. :)

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

Ik denk dat zoiets performance-wise en technisch het mooist is, maar moet je wel mysql 4.1 (of kon 4.0 nou ook al unions?) hebben:

code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
SELECT
  c.*
FROM
  companies c
WHERE
   c.companiesName LIKE '%".$searchString."%'
   OR
   c.companiesAddress LIKE '%".$searchString."%'

UNION

SELECT 
  c.*
FROM
  companies c
  LEFT JOIN keywords_companies kc ON c.companiesId=kc.companiesId
  INNER JOIN keywords k ON k.keywordsId=kc.keywordsId
  WHERE
   k.keywordsName LIKE '%".$searchString."%'


De union zorgt al voor een unieke resultaat tabel.

Overigens kan je met je eigen query ook al enkel de company-informatie opvragen door SELECT DISTINCT c.* FROM ... te doen.
Pagina: 1