Op deze website gebruiken we cookies om content en advertenties te personaliseren, om functies voor social media te bieden en om ons websiteverkeer te analyseren. Ook delen we informatie over uw gebruik van onze site met onze partners voor social media, adverteren en analyse. Deze partners kunnen deze gegevens combineren met andere informatie die u aan ze heeft verstrekt of die ze hebben verzameld op basis van uw gebruik van hun services. Meer informatie.

Akkoord

Vraag & Antwoord

Webprogrammeren & scripting

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

Remytje
15 antwoorden
  • 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
  • Heb je onderstaande al geprobeerd?

    SELECT bla
    FROM foo
    INNER JOIN bar
    ON
  • 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]
  • 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.
  • Bedankt Annie,

    Ze werkt, ik krijg nu alleen wat dubbele resultaten.
    SELECT DISTINCT… werkt niet vanwege de ORDER BY clause.
    Weet jij ook hoe ik dit kan oplossen?
  • Daarop kan ik alleen een antwoord geven als ik meer weet over je datamodel, de data die daar inzit en het beoogde resultaat (zoals ik in mijn vorige bericht vermeldde). Anders blijft het namelijk gissen naar een juist antwoord.
  • 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.
  • 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]
  • Oh sorry,

    Ik zal de url er meteen even bijzetten: www.studiecentrum.com
    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
  • 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.
  • 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?
  • Bij een GROUP BY mogen in de SELECT alleen de velden worden opgenomen waarop gegroepeerd worden of waarop een aggregated function is uitgevoerd (bijv MAX(), SUM(), AVG(), COUNT()).
  • Joh, ik heb er als ik het mij goed herinner met MySQL anders nooit problemen mee gehad…maar da's ook niet precies dezelfde syntax natuurlijk (wás het maar zo haha…).
  • 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?
  • Nee, niet echt, maar het is dan ook weekend :wink:

    Als ik er maandag niet uit kom, zou je me dan weer willen helpen?

    Bedankt en goed weekend!

    Hoi

Beantwoord deze vraag

Dit is een gearchiveerde pagina. Antwoorden is niet meer mogelijk.