Avatar billede tgl Nybegynder
20. juli 2004 - 14:02 Der er 20 kommentarer og
1 løsning

INNER JOIN i mange til mange relation

Jeg har en access-db hvor der er en mange til mange relation.

Derfor har jeg oprettet en såkaldt hjælpetabel som er "linket" mellem de to tabeller (tabel 1 og tabel 3) som jeg skal hente data fra.

Der skal hentes en hovedvare (intet problem i det) og de evt. tilhørende varer (= portefølje varer) som kan bestilles sammen med hovedvaren hvis brugeren ønsker det.

Dvs. der kan være fra 0..x antal proteføljevarer i tabel 3.


tabel 1 : indeholder alle varer
PK = catalogID

tabel 2 : hjælpetabel
catid = refererer til catalogID i tabel 1
pfid = referer til id for portefølje vare i tabel 3

tabel 3 : indeholder alle porteføljevarer som kan bestilles sammen med en hovedvaren.
pid = refererer til pdif i tabel 2.
catid = id for porteføljevare som igen refererer til dens id i tabel 1 hvor data er.


Har forsøgt mig med denne SQL :

Dim SQLportef, rsportef
SQLportef = "SELECT * FROM products INNER JOIN " &_
"(portefolje INNER JOIN prodport ON portefolje.Pid = prodport.pfid) " &_
"ON products.catalogID = prodport.catid " &_
"WHERE products.catalogID = prodport.catid AND products.catalogID = "&vareid&";"


Men det virker ikke.

hvad gør jeg forkert?????
Avatar billede kibeha Nybegynder
20. juli 2004 - 15:11 #1
Hej

Din where klausul kræver at catalogID for products både skal være lig prodport.catid OG skal være lig vareid - det kan ikke lade sig gøre samtidig :-)

Du må vist bruge alias til at skelne mellem products som hovedvare og products som porteføljevare.

Noget á la det her :

"select * from products hovedvare inner join " &_
  "(portefolje inner join " &_
    "(prodport inner join " &_
      "(products portvare " &_
      "on portvare.catalogID = prodport.catid) " &_
    "on prodport.pid = portefolje.pfid) " &_
  "on portefolje.catid = hovedvare.catid) " &_
"where hovedvare.catalogID = " & vareid & ";"

Her figurerer products tabellen 2 gange - en gang aliaset som 'hovedvare', en gang aliaset som 'portvare'.

Jeg er ikke sikker på det vil virke i Access, men jeg tror det :-)
Avatar billede tgl Nybegynder
20. juli 2004 - 15:20 #2
Det ser rigtigt ud og har nu prøvet at afvikle den på en asp-side, men får denne fejlmeddelse :

Microsoft JET Database Engine fejl '80040e14'
Der er en syntaksfejl i JOIN-handlingen




Dim SQLportef, rsportef
SQLportef = "Select * FROM products hovedvare INNER JOIN " &_
"(portefolje INNER JOIN " &_
"(prodport INNER JOIN " &_
"(products portvare " &_
"ON portvare.catalogID = prodport.catid) " &_
"ON prodport.pid = portefolje.pfid) " &_
"ON portefolje.catid = hovedvare.catid) " &_
"WHERE hovedvare.catalogID = " & vareid & ";"
Avatar billede kibeha Nybegynder
20. juli 2004 - 15:39 #3
Tre mulige ting:


Den ene ting jeg lige har bemærket er, at linien :

"ON prodport.pid = portefolje.pfid) " &_

måske skal være :

"ON prodport.pfid = portefolje.pid) " &_

Jeg kan ikke helt gennemskue fra dit spørgsmål hvilket af tabellerne der bruger 'pfid' og hvilket bruger 'pid' :-) Så det kan du prøve først.


Den anden ting er at jeg tror jeg har en parentes for meget - måske skal det i stedet være sådan her :

"select * from products hovedvare inner join " &_
  "(portefolje inner join " &_
    "(prodport inner join " &_
      "products portvare " &_
      "on portvare.catalogID = prodport.catid) " &_
    "on prodport.pid = portefolje.pfid) " &_
  "on portefolje.catid = hovedvare.catid " &_
"where hovedvare.catalogID = " & vareid & ";"

Det kan du så prøve som mulighed 2.


Den tredje ting er, at jeg (måske fejlagtigt) troede at syntaxen mindede om MS SQL.
Men jeg er faktisk ikke helt sikker på om Access understøtter det at lave alias på en tabel i et select ?
Det kan i stedet godt være, at Access benytter parenteserne til at skelne, og i så fald kan måske følgende virke :

"select * from products inner join " &_
  "(portefolje inner join " &_
    "(prodport inner join " &_
      "products " &_
      "on products.catalogID = prodport.catid) " &_
    "on prodport.pid = portefolje.pfid) " &_
  "on portefolje.catid = hovedvare.catid " &_
"where products.catalogID = " & vareid & ";"


Så der var tre muligheder for dig at prøve af.

Jeg har ikke selv mulighed her for at teste det - så jeg kan ikke garantere du kan cut/paste min kode 100% korrekt :-)
Avatar billede tgl Nybegynder
20. juli 2004 - 16:17 #4
Ja, det skal være "ON prodport.pfid = portefolje.pid) " &_.
Har rettet til.

Længere nede skrev du "ON portefolje.catid = hovedvare.catid) " &_, men så vidt jeg kan se skal det være "ON portefolje.catid = products.catalogID) " &_

Bare for at være sikker er her hvad jeg mener der sker i SQL-sætningen :
---------------------------------------
JOIN 1 :
"(prodport INNER JOIN " &_
"(products ON products.catalogID = prodport.catid) " &_
"ON prodport.pfid = portefolje.pid) " &_

Forklaring :
Først hentes først alle catalog-id'er over i products-tabellen som matcher hinanden i products og prodport-tabellerne.
Derefter hentes alle alle portefølje-id'er over i prodport-tabellen som matcher hinanden ud fra ovenstående resultat i products-tabellen.
--------------------------------------------

JOIN 2 :
"(portefolje INNER JOIN " &_
...
"ON portefolje.catid = products.catalogID) " &_


Forklaring :
Resultatet fra JOIN 1 filtreres endnu engang så også matchende catalog-id'er i portefolje og products-tabellen hentes.


Til sidst hentes, via de udtrukne poster i JOIN 2, porteføljevarerenes data i products -tabellen ud fra en bestemt hovedvare.


Håber jeg har forstået det rigtigt.



Dim SQLportef, rsportef
SQLportef = "SELECT * FROM products INNER JOIN " &_
"(portefolje INNER JOIN " &_
"(prodport INNER JOIN " &_
"(products ON products.catalogID = prodport.catid) " &_
"ON prodport.pfid = portefolje.pid) " &_
"ON portefolje.catid = products.catalogID) " &_
"WHERE products.catalogID = " & vareid & ";"
----------------------------------------------

Men jeg får nu denne fejl :

Microsoft JET Database Engine fejl '80040e14'
Der er en syntaksfejl i JOIN-handlingen
Avatar billede eagleeye Praktikant
20. juli 2004 - 19:06 #5
Dine INNER JOIN er bygget forkert op. Prøv sådan her:

SQLportef = "SELECT * FROM (products INNER JOIN " &_
"prodport ON products.catalogID = prodport.catid) " &_
"INNER JOIN portefolje ON prodport.pfid = portefolje.pid " &_
"WHERE products.catalogID = "&vareid&";"


Hvis du har access installeret kan du bruge access indbyggede Query builder eller på danske "Forspørgelser" til at bygge din SQL ud fra dine tabeller. Du kan angive relationen imellem tabellerne.
Avatar billede tgl Nybegynder
20. juli 2004 - 19:22 #6
eagleeye >> jeps, det virker.

Eller rettere jeg får hovedvarens data udtrukket og det var egenlig portefølje varernes data jeg skulle have.
Avatar billede eagleeye Praktikant
20. juli 2004 - 19:24 #7
Du kan rette:

SQLportef = "SELECT * FROM

til denne sådan den kun henter data fra portefølje tabllen:

SQLportef = "SELECT portefolje.* FROM
Avatar billede tgl Nybegynder
20. juli 2004 - 19:24 #8
Lidt mere forklaring : vareid som står sidst i SQL'en er hovedvarens id i produkttabellen og ud fra den skal porteføljevarernes data hentes.

Porteføljevarerne er også en del af produkttabellen.
Avatar billede tgl Nybegynder
20. juli 2004 - 19:31 #9
Har prøvet at rette til og får denne besked :

"Elementet kan ikke findes i den samling, der svarer til det anmodede navn eller ordenstal.
ADODB.Recordset fejl '800a0cc1'"

SQL output :

SELECT portefolje.* FROM (products INNER JOIN prodport ON products.catalogID = prodport.catid) INNER JOIN portefolje ON prodport.pfid = portefolje.pid WHERE products.catalogID = 19;
Avatar billede tgl Nybegynder
20. juli 2004 - 19:32 #10
Har prøvet at hente navn på porteføljevaren som i tabellen hedder cname :

response.write rsportef("cname")
Avatar billede eagleeye Praktikant
20. juli 2004 - 19:46 #11
Er cname en kolonne i tabellen portefolje?
Avatar billede eagleeye Praktikant
20. juli 2004 - 19:49 #12
jeg er ikke helt sikker på jeg forstår det du skriver her:

Porteføljevarerne er også en del af produkttabellen.

Så porteføjetabellen skal hente data omkring varen i produkt tabelen?
Avatar billede tgl Nybegynder
20. juli 2004 - 19:51 #13
Så porteføjetabellen skal hente data omkring varen i produkt tabelen?
Ja, det er der data for porteføljevarer også er.

Dvs. en vare kan være både portefølje og en selvstædniug vare.
Avatar billede eagleeye Praktikant
20. juli 2004 - 19:57 #14
Ok så må SQL udvides med en INNER JOIN mere, her giver man også tabellen et alias sådan det tolkes som to tabeller:

SELECT products_data.* FROM ((products INNER JOIN prodport ON products.catalogID = prodport.catid) INNER JOIN portefolje ON prodport.pfid = portefolje.pid) INNER JOIN products as products_data ON portefolje.catid=products_data.catalogID WHERE products.catalogID = 19;
Avatar billede tgl Nybegynder
20. juli 2004 - 20:08 #15
Jeps, nu virker det.

Så skal jeg bare have loopet mit portefølje recordset for at få det udskrevet på siden.
Avatar billede eagleeye Praktikant
20. juli 2004 - 20:18 #16
Ók, mener du udskrevet det som den finder?
Avatar billede tgl Nybegynder
20. juli 2004 - 20:23 #17
Ja, de portefølje varer som findes til hovedvaren skal udskrives.
Avatar billede eagleeye Praktikant
20. juli 2004 - 20:27 #18
du laver et loop som dette:


SQLportef = "din sql sætning"
Set rs = Conn.Execute(SQLportef)

do while not rs.EOF
  Response.Write rs("cname") & "<br>"

  rs.Movenext
loop


Du kan evt. bygge en tabel omkring hvis du har flere kolonner der skal vises:

Set rs = Conn.Execute(SQLportef)
Response.Write "<table>"
Response.Write "<tr><td>Navn</td><td>beskrivelse</td></tr>"
do while not rs.EOF
  Response.Write "<tr>"
  Response.Write "<td>" & rs("cname") & "</td>"
  Response.Write "<td>" & rs("beskrivelse") & "</td>"

  Response.Write "</tr>"
  rs.Movenext
loop
Response.Write "</table>"
Avatar billede tgl Nybegynder
20. juli 2004 - 20:42 #19
Fint, jeg takker for hjælpen.

Vil gerne give dig point, men så skal du først afgive et svar så vidt jeg har forstået dette system.
Avatar billede eagleeye Praktikant
20. juli 2004 - 20:44 #20
Det er helt korrekt, jeg laver da meget gerne et svar :)
Avatar billede tgl Nybegynder
20. juli 2004 - 20:47 #21
Udmærket, her er point.
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester



IT-JOB