Ga naar inhoud

Probleem met meerdere (inner/outer) joins in SQL-query


anoniem

Aanbevolen berichten

Hoi, Ik probeer al een hele tijd de resultaten van een query op drie 'gejoinde' tabellen te krijgen. Ik wil namelijk een lijst van producten laten sorteren op datum in plaats van sorteren op alfabet. Omdat het datumveld hiervoor, V_Date in de derde tabel Versions staat dacht ik dit met een join of subselect gemakkelijk op te lossen. De velden V_Product in Versions en P_ID in Products zijn te gebruiken voor de JOIN. Ik krijg echter steeds de volgende irritante error: [code:1:445b685a95] Microsoft JET Database Engine error '80040e14' Syntax error (missing operator) in query expression 'Products.P_ID = VerJoin.V_Product INNER JOIN Prodtype ON Products.P_Prodtype = Prodtype.PT_ID'. [/code:1:445b685a95] Dit is mijn SQL-querystring: [code:1:445b685a95] theQuery = "SELECT * FROM Products LEFT OUTER JOIN (SELECT * FROM Versions WHERE V_Product = " & prodtype & ") VerJoin ON Products.P_ID = VerJoin.V_Product INNER JOIN Prodtype ON Products.P_Prodtype = Prodtype.PT_ID WHERE (((Products.P_Prodtype)=" & prodtype & ")) ORDER BY VerJoin.V_Date, Products.P_Name ;" [/code:1:445b685a95] Kan iemand mij even helpen aub? Bedankt
Link naar reactie
Heb je onderstaande al geprobeerd? SELECT bla FROM foo INNER JOIN bar ON [color=red:0958676552][b:0958676552]([/b:0958676552][/color:0958676552]a=b[color=red:0958676552][b:0958676552])[/b:0958676552][/color:0958676552] enz.. Het leest overigens makkelijker als je bij het debuggen van je query de versie geeft die je aan de database geeft. Dus [color=blue:0958676552]response.write theQuery[/color:0958676552] en dan deze output. Nu moet je zelf nog alle variabelen "invullen".
Link naar reactie
Bedankt voor je reactie Annie, - Ja, dat heb ik ook geprobeerd. response.write theQuery geeft: [code:1:1da1fe8328] SELECT * FROM Products LEFT OUTER JOIN (SELECT * FROM Versions WHERE V_Product = '15') VerJoin ON Products.P_ID = VerJoin.V_Product INNER JOIN Prodtype ON Products.P_Prodtype = Prodtype.PT_ID WHERE Products.P_Prodtype = '15' ORDER BY VerJoin.V_Date,Products.P_Name; [/code:1:1da1fe8328]
Link naar reactie
Poging 2: [code:1:4a81b05c53] SELECT * FROM ( Products INNER JOIN ProdType ON (ProdType.PT_ID = Products.P_ProdType) ) LEFT OUTER JOIN Versions ON (Products.P_ID = Versions.V_Product) WHERE Products.P_Prodtype = '15' ORDER BY Versions.V_Date, Products.P_Name [/code:1:4a81b05c53] Als deze niet voldoet is het misschien handig als je ook even aangeeft hoe je model verder in elkaar steekt, wat je data is en wat je uiteindelijk verwacht als resultaat.
Link naar reactie
OK. Het gaat dus om het juist sorteren van een productenlijst. Deze producten staan in de tabel Products. In de tabel ProdType worden de verschillende producttypen bewaard en in Versions staan de verschillende versies van de producten en bevat het veld V_Date dat ik wil gebruiken voor het sorteren (van 'vroeger' naar 'later', dus gewoon ASC). Het script: [code:1:6e6f7c0915] '----------------------------------------------- 'CONNECT TO DATABASE '----------------------------------------------- Set DataConn = Server.CreateObject("ADODB.Connection") DataConn.Open datasourcename Set cmdTemp = Server.CreateObject("ADODB.Command") Set rs_main = Server.CreateObject("ADODB.Recordset") Set rs_main2 = Server.CreateObject("ADODB.Recordset") %> <body background="<% =pagebg %>" bgcolor="<% =pagecolor %>" text="<% =pagetext %>" link="<% =pagelink %>" vlink="<% =pagevlink %>" alink="<% =pagealink %>"> <div align="<% =pagealign %>"> <table border="0" cellpadding="0" cellspacing="0" width="580"> <tr> <td valign="top"><img src="../images_webshop/spacer.gif" width="35" height="5"></td> <td valign="top" align="left"><img src="../images_webshop/spacer.gif" width="450" height="5"><br> <% '----------------------------------------------- 'PULL OUT PRODUCTS/PRODTYPES FROM DATABASE '----------------------------------------------- theQuery2 = "SELECT DISTINCTROW [P_ID], [P_Name], [P_Comment], [P_Desc], [P_ProdType], [P_Hyperlink], [P_Featured], [P_SpecTable] FROM ( Products INNER JOIN ProdType ON (ProdType.PT_ID = Products.P_ProdType) ) LEFT OUTER JOIN Versions ON (Products.P_ID = Versions.V_Product) WHERE Products.P_Prodtype = " & prodtype & " ORDER BY Versions.V_Date;" theQuery = "SELECT * FROM Products INNER JOIN Prodtype ON Products.P_Prodtype = Prodtype.PT_ID WHERE (((Products.P_Prodtype)=" & prodtype & ")) ORDER BY Products.P_Name ;" cmdTemp.CommandText = theQuery cmdTemp.CommandType = 1 Set cmdTemp.ActiveConnection = DataConn rs_main.Open cmdTemp, , 1, 3 IntNumRecs = rs_main.RecordCount If IntNumRecs=0 then %> <font face="verdana" size="2"><b>OP DIT MOMENT ZIJN HIER GEEN ITEMS BESCHIKBAAR</b></font> <% else %> <font face="verdana" size="4" ><font face="verdana" size="4" ><b> <% varProduct = rs_main("P_Prodtype") Select Case True Case varProduct > 10 AND varProduct < 15 Response.Write "" Case varProduct > 0 AND varProduct < 10 Response.Write "Boeken met Samenvatting" Case varProduct = 29 Response.Write "Boeken met Samenvatting" Case varProduct = 35 Response.Write "Boeken met Samenvatting" Case varProduct > 14 AND varProduct < 26 Response.Write "" End Select %> </b></font><br> <font face="verdana" size="2"><b><% response.write(rs_main("PT_Name")) %></b></font><hr size="1" color="#C0C0C0"> <% response.write(rs_main("PT_Desc")) %></font><br> <hr size="1" color="#C0C0C0"> <table border="0" cellpadding="0" cellspacing="0" width="450"> <% '----------------------------------------------- 'COUNT THROUGH FIRST FEW RECORDS IF NOT PAGE 1 'OK, it's bodge but stops us having to hold 'recordsets in sessions. '----------------------------------------------- If recor<>1 then do until CInt(recordnumber)=CInt(recor-1) recordnumber = recordnumber + 1 rs_main.movenext loop end if do while recordnumber<(recor+prodtypepagesize-1) AND not rs_main.EOF recordnumber = recordnumber + 1 %> <tr> <td><font face="verdana" size="2"><b><% =recordnumber %>.&<a href="product.asp?product=<% response.write(rs_main("P_ID")) %>"><% response.write(rs_main("P_Name")) %></a></b></font></td> </tr> <tr> <td height="140" valign="top"><font face="verdana" size="2"> <% if rs_main("P_Image") <>"" then %><a href="product.asp?product=<% response.write(rs_main("P_ID")) %>"> <img src="../productpics/<% response.write(rs_main("P_Image")) %>" border="0" hspace="10" vspace="10" align="left"></a> <% end if %> <% response.write(rs_main("P_Comment")) %> <br> <br> <a href="product.asp?product=<% response.write(rs_main("P_ID")) %>"> <% strProduct = rs_main("P_Prodtype") If strProduct >0 AND strProduct <10 OR strProduct =35 OR strProduct =29 Then Response.Write "<img src=../images_algemeen/bestel.jpg width=139 height=25 border=0 align=right >" Else Response.Write "<img src=../images_algemeen/inschrijven.gif width=222 height=25 border=0 align=right>" End If %> </a></font><br> <img src="../images_webshop/spacer.gif" width="10" height="35" ></td> </tr> <% rs_main.moveNext loop rs_main.Close DataConn.Close set DataConn = nothing '----------------------------------------------- 'THIS SECTION GENERATES PREV/NEXT AND PAGE NOS. 'Looks worse that it is. Just decides whether or 'not a 'next' or 'previous' button is needed, 'whether any page numbers are needed and then 'displays them. It will black out the page you 'are on so you can recall it, just like a big 'boy's search engine does. '----------------------------------------------- %> <tr> <td align="center"><hr size="1" color="#C0C0C0"><b><font face="verdana" size="2"><% if recordnumber>prodtypepagesize then %> <a href="prodtype.asp?prodtype=<% =prodtype %>&recor=<% =recor-prodtypepagesize %>"><< vorige</a> <% end if %> <% If IntNumRecs > prodtypepagesize then for t = 1 to CInt((IntNumRecs/prodtypepagesize)+0.49) %> &<% If Cint(recor)<>(prodtypepagesize*(t-1))+1 then %><a href="prodtype.asp?prodtype=<% =prodtype %>&recor=<% =(prodtypepagesize*(t-1))+1 %>"><% =t %></a><% else response.write(t) end if next End if if IntNumRecs>recordnumber then %> &<a href="prodtype.asp?prodtype=<% =prodtype %>&recor=<% =recor+prodtypepagesize %>">volgende &&</a></font></b> <% end if %> [/code:1:6e6f7c0915] De stringvar theQuery bevat de de oude query, theQuery2 is de aangepaste versie. Als ik deze laatste query verder aanpas met DISTINCTROW... krijg ik niet het juiste resultaat, omdat het datumveld V_Date niet wordt 'meegejoined'. Als ik het met SELECT DISTINCT probeer, krijg ik een error dat DISTINCT en de ORDER BY clause niet samengaan.
Link naar reactie
Hmm, communicatie storing :) Ik bedoelde eigenlijk iets meer inzicht in je database en niet zozeer je code. Zo'n brok asp code heb ik niet zoveel zin in om te gaan doorlopen en bovendien weet ik dan nog steeds niet of een query wel of niet voldoet aan je eisen. Waar ik meer aan heb is bijvoorbeeld iets als onderstaande en dat in combinatie met wat uitleg over de relatie tussen de tabellen. [code:1:a6344a52c9] Products P_ID | P_Name | P_ProdType -------------------------- 1 prod A 10 2 prod B 15 3 prod C 10 4 prod D 24 ProdType PT_ID | PT_Description ---------------------- 10 type 10 15 type 15 24 type 24 30 type 30 Versions V_ID | V_Product | V_Date --------------------------- 1 1 01-12-02 2 1 01-01-03 3 2 01-05-01 4 4 01-01-03 5 3 01-02-03 Beoogd resultaat P_Name | PT_Description | V_Date ---------------------------------- prod A type 10 01-12-02 prod A type 10 01-01-03 prod C type 10 01-02-03 [/code:1:a6344a52c9]
Link naar reactie
Oh sorry, Ik zal de url er meteen even bijzetten: [url]www.studiecentrum.com[/url] Mocht je het even willen bekijken: - klik op 'Avondcolleges' - Kies in het uit het linker menu een item, bijv. 'Algemeen Management' Er verschijnt een nu een overzicht van de avondcolleges, ofwel de productenlijst. Deze lijst moet op datum gesorteerd worden. Het probleem is dat de productentabel Products geen datumveld heeft, omdat alle uitgebreide 'versieinformatie' opgeslagen wordt in de Versions-tabel. Als er meer dan één versie van een product/college is, dan moet de versie met de vroegste datum gebruikt worden bij sorteren. Al met al betekent dit dat ik in ieder geval Versions met Products moeten joinen. De productkoppeling tussen Products en Versions kan gemaakt worden met Products.P_ID en Versions.V_Product. De ProdType-tabel zorgt voor de categoriekoppeling, zoals bijv. 'Algemeen Management', d.m.v. de velden ProdType.PT_ID en Products_P_ProdType. Products.P_Image, Products.P_Desc, Products.P_Comment en P_Featured worden gebruikt voor het weergeven o.a. van de titel, een onderschrift en een brochureimage. De overige velden bij alle drie de tabellen zijn niet of minder belangrijk en dit geldt ook voor de datatypen lijkt mij. Eh heb je zo genoeg informatie? Bedankt
Link naar reactie
Ik heb geen tijd meer om er uitgebreid naar te kijken. Misschien dit weekend even. Maar zo op het eerste gezicht denk ik dat je naast het JOIN-en ook een GROUP BY moet uitvoeren op de producten om je "dubbele" entries weg te halen. Voor de laatste versie kan je dan de aggregate functie MAX() gebruiken op de datum kolom. Misschien dat je daar al wat verder mee komt, zo niet dan kijken we later wel even verder.
Link naar reactie
Hee ja, GROUP BY... :) Even proberen: [code:1:9fc7aad33f] theQuery = "SELECT * FROM ( Products INNER JOIN ProdType ON (ProdType.PT_ID = Products.P_ProdType) ) LEFT OUTER JOIN Versions ON (Products.P_ID = Versions.V_Product) WHERE Products.P_Prodtype = " & prodtype & " GROUP BY Products.P_Name ORDER BY Versions.V_Date;" [/code:1:9fc7aad33f] geeft: [code:1:9fc7aad33f] Microsoft JET Database Engine error '80040e21' Cannot group on fields selected with '*'. /www/pages/pages_middle/asp/prodtype.asp, line 48 [/code:1:9fc7aad33f] Hoezo niet?
Link naar reactie
Offtopic: Dat MySQL het wel ondersteund wil niet zeggen dat andere databases dat ook doen. Iedere database heeft zo zijn eigen SQL dialect. [quote:7a08322ebf](wás het maar zo haha...)[/quote:7a08322ebf] Gelukkig niet, ik moet er niet aan denken dat de [i:7a08322ebf]echte[/i:7a08322ebf] databases dezelfde syntax als MySQL zouden gebruiken :lol: . Ontopic: Ben je al wat verder gekomen?
Link naar reactie
Als ik hier naar kijk, dan zou ik vanuit de tabel 'Versions' beginnen met mijn SQL-string en vanaf daar opbouwen\uitbreiden, aangezien de tabel 'Versions' de basistabel is voor mijn benodige output. De overige tabellen zijn alleen voor extra informatie voor de benodigde output. Ik zou bv eerst zorgen dat ik de alle versies krijg met de oudste datum, door bv:[code:1:829e63a583]SELECT V_Product, MIN(V_Date) AS V_DateMin FROM Versions GROUP BY V_Product[/code:1:829e63a583]En vanuit hier de gegevens bij te voegen van Products en ProductTypes. Volgens mij kun je hiermee voorkomen dat je een LEFT JOIN (die voor een langere verwerking zorgt) moet gebruiken. Ik heb het bovenstaande nog niet uitgeprobeerd, maar het is mogelijk een andere oplossing voor je probleem.
Link naar reactie

Om een reactie te plaatsen, moet je eerst inloggen

Gast
Reageer op dit topic

×   Geplakt als verrijkte tekst.   Herstel opmaak

  Er zijn maximaal 75 emoji toegestaan.

×   Je link werd automatisch ingevoegd.   Tonen als normale link

×   Je vorige inhoud werd hersteld.   Leeg de tekstverwerker

×   Je kunt afbeeldingen niet direct plakken. Upload of voeg afbeeldingen vanaf een URL in

×
×
  • Nieuwe aanmaken...