[MySql] Selecteren van tabellen en die joinen

Pagina: 1
Acties:

  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
Ik heb de volgende query(1). Hiermee krijg ik de laatste 5 reacties die gegeven zijn op een nieuws bericht.
Nu zijn er ook andere onderdelen waarbij reacties kunnen worden gepost bijv in de tabel film. Het probleem is dan dat de titel uit de nieuws tabel moet worden gehaald, of uit de filmtabel en in de toekomst komen daar nog meer tabellen bij. Probleem is dat je aan de hand van reactie.onderdeel moet bepalen welke tabel moet worden gebruikt om de titel uit te halen.

Ik heb al ruim een uur allerlei mogelijke IF variaties geprobeerd, maar zonder succes

Query 1:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
SELECT 
    reactie.id,
    reactie.datum,
    reactie.onderdeel,
    reactie.parentid,
    nieuws.titel,
    nieuws.id               
FROM
    nieuws,
    reactie                 
WHERE
    nieuws.id = reactie.parentid
ORDER BY
    reactie.datum
DESC
LIMIT
    5


Reactie Tabel
code:
1
2
3
4
5
id  onderdeel   parentid    gebruikerid datum   inhoud
-------------------------------------------------------------
1       n           2       3           1023435 Blaat1 op nieuws
2       n           1       1           1685775 Blaat2 op nieuws
3       f           3       2           1248598 Blaat3 op film

De n staat voor nieuws en de f voor film. Parent id geeft het id van het bericht aan waar de reactie op is gepost.
Nieuws Tabel
code:
1
2
3
4
5
id  titel   
-------------------------------------------------------------
1       Blaat
2       Foo
3       Farm


Film Tabel
code:
1
2
3
4
5
id  titel
-------------------------------------------------------------
1       Sesamstraat
2       PietjePuk
3       RoadHouse


Ik werk met PHP 4.2.1, MySql en Apache op Slackware.
edit:
Even een duidelijker voorbeeld genomen, want met de gebruikerstabel veroorzaakte wat verwarring

[ Voor 15% gewijzigd door commeric op 04-11-2003 22:29 ]


  • whoami
  • Registratie: December 2000
  • Laatst online: 17:38
Ik weet niet of ik je probleem volledig snap, maar kan je niet uit de voeten met dit:

code:
1
2
3
4
SELECT reactie.inhoud, nieuws.titel, gebruiker.naam
FROM reactie, nieuws, gebruiker
WHERE reactie.gebruikerid = gebruiker.id
AND reactie.parentid = nieuws.id

:?

https://fgheysels.github.io/


  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
Ik heb nu even een duidelijker voorbeeld genomen, want de combinatie met de gebruikerstabel zorgde voor wat verwarring. Daardoor kan ik helaas whoami oplossing ook niet gebruiken.
Het gaat er namelijk om dat aan de hand van reactie.onderdeel de tabel wordt bepaald waaruit de titel wordtgehaalt. En wat jij doet is gewoon een gebruikersnaam uit de gebruikerstabel en een titel uit de nieuwstabel bij de reactie zoeken.

  • mr_obb
  • Registratie: Juni 2001
  • Laatst online: 12:59

mr_obb

Lakse Perfectionist

Je wil dus iets selecteren uit de tabel waarvan de naam gelijk is aan die van reactie.onderdeel?

  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
mr_obb schreef op 04 november 2003 @ 22:00:
Je wil dus iets selecteren uit de tabel waarvan de naam gelijk is aan die van reactie.onderdeel?
bijna gelijk
de waarde die in reactie.onderdeel voorkomen zijn: n en f. En als er n uit reactie.onderdeel komt dan moet de titel uit de tabel nieuws worden gehaald. Komt er f uit reactie.onderdeel dan moet de titel uit de film tabel worden gehaald

[ Voor 3% gewijzigd door commeric op 04-11-2003 22:05 ]


  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 11-06 07:23
ehm

heel simpel?

koppeltabel maken

die zegt "n = nieuws" en "g = film iets"
en dan beetje klooien, of misschien zoiets:

code:
1
2
3
select * from reakties
inner join (if reaktie.onderdeel='n' { $tabel='nieuws'} else { $tabel='films'} $tabel 
on reaktie.parentid = $tabel.id


ofzo......

mja, goed, je zal eerst een tussen stap moeten maken en al je N/G dingen eruit halen......

dan aan de hand van die tussen resultaten door je set heen lopen, je houdt dan een variabele bij die je steeds koppelt aan je n/g tussen resultaat. Daarmee kan je dan een if doen "if n -> dan nieuws tabel"

Het handigste is dus om die tabel naam ook in een variabele te doen, kan je het later met een switch statement gaan doen als je dat met meerdere tabellen wil gaan doen.

Btw, welke programmeer omgeving moet dit? PHP? Welke database? OBDC? MySQL?

Is het een Access databaseje? VBSCript? Moet het op een SQL2000 server draaien en wil je er een stored procedure van maken?

Tja, het kan op legio manieren, maar je zult er denk ik niet aan ontkomen door eerst een tussen resultaat op te halen voor je n/g bepalingen, want anders kom je niet echt handig bij je gegevens (je kan niet midden in je select echt zo makkelijk hmmmm hoewel, nja user defined function....... ach, het ligt echt helemaal aan je omgeving).

JA IK BEN WAKKER. MySQL dus...... hehehe, nu nog, welke scripttaal? php zeker?
dan is het niet zoooooooo moeilijk.

2 setjes binnen halen......

of ehmz, waarom doe je moeilijk?


je hebt een tabel met daarin

N, G, F als keys, en "nieuws, gebruiker, films" als tabel naam....

dan is het toch makkelijk?
code:
1
2
3
select reakties.*, films.titel from reakties
inner join films on reakties.id = films.id
where reakties.onderdeel = n


Dat is voor 1 specifiek onderdeel, nu hoef je dat alleen nog maar variabel te maken, in een functie te proppen. en dan kan je zeggen

code:
1
2
3
4
5
6
7
8
9
10
getItems($type)
{
switch($type)
 case "n": $tabel=nieuws; break;
 case "f": $tabel = films; break;

select reakties.*, $tabel.titel from reakties
inner join $tabel on reakties.id = $tabel.id
where reakties.onderdeel = $type
}


Of wil je het echt in 1 grote select meteen goed gejoined hebben? :P

[ Voor 28% gewijzigd door cavey op 04-11-2003 22:19 ]


  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
komakeef bedankt voor je reactie! Ik ga het gelijk proberen.
Ik werk met PHP 4.2.1, MySql en Apache op Slackware.

  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 11-06 07:23
kant tekening: de code is slechts ter illustratie en ik garandeer absoluut niet dat het 100% werkt, zolang het idee maar beetje overkomt.

good luck

  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
Dit is idd een manier om het op te lossen. Het nadeel hierbij is dat je, als het tegen zit 5 querys moet gaan uitvoeren. En dat kost nogal wat preformace. Ik probeer daarom ook naar een oplossing te zoeken waarbij alles in 1 (grote) query zit

  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 11-06 07:23
mja

het kan misschien, als je met mysql of php direct in de query wat dingen kan gaan aanpassen.

Maar wat je in weze aan het doen bent, is de hele tijd je query on the fly rebuilden.

Wat dan denk ik toch beter is, om de boel per category te ordenen.... en dat je toch met 5 losse queries gaat zitten.

Want bedenk wel: als je 5 verschillende types hebt, en je hebt het op jouw manier opgelost. hmmz..

Misschien is het makkelijker om 1 tabel te hebben met titels?

en dat je daarin een subcategorie specificeert, ipv in je reakties tabel?

Je verschuift het probleem dan naar een iets hapklaardere plek:

category
code:
1
2
3
1 : films
2 : gebruikers
3 : nieuws


titels
id, fk_category, titel
code:
1
2
1 : 1 : BLAAAAAAAT
2 : 2 : BLAAAAAAAAT


[/code]
reaktie tabel, fk_titels
[code]

en dat je dan de boel zo weer aan mekaar knoopt om toch je categorien te weten:
select reakties.*, titels.*, category.naam
from reakties
inner join titels on reaktie.titel_id = titel.id
inner join category on category.id = titel.fk_category
where ehmz
group by category_id
(of een order by doen... nagoe, zie maar hoe je het wilt groeperen).

(met SQL2000 heb je het probleem met group by dat je elk veld wat je select ook apart moet benoemen.... kweet niet in hoeverre dat ook met MySQL is).


Dus met een iets ander database ontwerp, kan je er makkelijker uit komen denk ik zo....... titels in 1 tabel flikkeren met een vreemde sleutel id (bij voorkeur met id's werken!!!) voor je category omschrijving....

  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
Daar heb je idd wel gelijk in dat je elke keer die query weer rebuild. Het aanmaken van zon extra tabel kost alleen maar preformance, en ik hoop het op een zo net mogelijke manier doen. Dus zo veel mogelijk in 1 query

Ik heb nu deze query inelkaar gezet. Tot dusver werkt ie nog goed. Iemand nog
commentaar, of opmerkingen hierover?
code:
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
SELECT
DISTINCT 
    reactie.id,
    reactie.datum,
    reactie.onderdeel,
    reactie.parentid,               
    case 
    when reactie.onderdeel='n' 
        then nieuws.titel
    when reactie.onderdeel='f' 
        then film.titel
    end as titel        
FROM 
    reactie,
    nieuws,
    film
WHERE
    case 
    when reactie.onderdeel='n' 
        then nieuws.id = reactie.parentid
    when reactie.onderdeel='f' 
        then film.id = reactie.parentid
    end 
ORDER BY
    reactie.datum DESC
LIMIT
    5

[ Voor 36% gewijzigd door commeric op 04-11-2003 23:19 ]


  • Gert
  • Registratie: Juni 1999
  • Laatst online: 05-12-2025
Ik zou eens naar union kijken.
Selecteer reacties die bij nieuws horen, union reacties die bij films horen, order by datum en limit 5 en je hebt hetzelfde, als het goed is. ;)

Union wordt ondersteund vanaf MySql 4.0.12 dacht ik.

  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 11-06 07:23
hey lachen dat je in mysql 4.0 (of kan het ook in 3.x?) in die where clause een case switch kan gebruiken!

maakt het niet echt flexibel/hanteerbaar als er meer bij komen.

maar hmmz ;)


trouwens, over een extra tabel: een extra koppeltabel maken of look-up tabel kost denk ik minder tijd dan steeds een query herbouwen ... het vreet wel iets meer resources...

  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
Ik gebruik MYSql versie 3.23.49 :).

  • Mickman
  • Registratie: Juni 2001
  • Laatst online: 29-03 18:11
Als je nou in het begin goed had genormaliseerd had je deze situatie niet gehad. Wat is het nu om film en nieuws uit elkaar te houden, wanneer ze allebei dezelfde soort attributen bevatten. Dan verplaats je het attribuut onderdeel van reactie naar nieuws/film. Dan heb je altijd het goede onderwerp.

  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 11-06 07:23
Mickman schreef op 05 november 2003 @ 08:12:
Als je nou in het begin goed had genormaliseerd had je deze situatie niet gehad. Wat is het nu om film en nieuws uit elkaar te houden, wanneer ze allebei dezelfde soort attributen bevatten. Dan verplaats je het attribuut onderdeel van reactie naar nieuws/film. Dan heb je altijd het goede onderwerp.
Hehe, dit bedacht ik me ook op de fiets vanochtend naar werk:

WAAROM ga je in je reaktie tabel een categorie bijhouden om aan de hand daarvan je juiste titel tabel te bepalen...... als je het categorie attribuut veel beter in de titel tabel kan gooien.. en dan een directe verwijzing in je reaktie tabel naar de juiste titel.

Het is toch autonummering, geen dubbele records mogelijk en als je de categorie erbij wilt hebben, dan inner join je die gewoon met je losse categorie tabel.

Want het wordt een onwerkbare situatie als je 10 vercshillende titel tabellen gaat hebben....... DAT geeft een grotere performance impact op je query dan een stel joins (waar een database toch voor geoptimaliseerd is)

good luck ^_^ Beter database ontwerp zorgt voor minder kludges. ;)

  • commeric
  • Registratie: November 2002
  • Laatst online: 01-07 08:51
Is het misschien nog een slimmere optie (qua preformance) als ik gewoon in de reactie tabel een veld maak 'titel' en daarin de titel neerzet die bij de reactie hoort.

[ Voor 13% gewijzigd door commeric op 05-11-2003 16:28 ]


  • cavey
  • Registratie: Augustus 2000
  • Laatst online: 11-06 07:23
nah, dan kan je niet echt meer bijvoorbeeld een overzicht van titels maken per genre.....

het is trouwens wel makkelijk om genres in een aparte tabel te zetten, want als je eens een genre van naam wil veranderen...... hoef je maar 1 keer een record te updaten... anders moet je je hele reakties tabel updaten....
Pagina: 1