Toon posts:

[SQL]Query optimalisatie

Pagina: 1
Acties:

Verwijderd

Topicstarter
Ik ben momenteel bezig met het bouwen van een query om de meest recente items uit een tabel op te halen. Dat is goed gelukt:

SQL:
1
2
3
4
5
6
7
8
SELECT t.strResearchThema AS Thema, "WAAR" AS Scan, b.strBedrijfnaam AS Name_ING, o.strOpinie AS SubtekstNL, n.strNFIText
FROM tblNFIAlgemeen AS n RIGHT JOIN ((tblBedrijven AS b INNER JOIN tblOpinie AS o ON b.intBedrijfID = o.intBedrijfID) INNER JOIN tblResearchThema AS t ON o.intResearchThemaID = t.intResearchThemaID) ON n.intBedrijfID = b.intBedrijfID
WHERE o.intResearchThemaID In (SELECT intThemaID FROM tblTempPortefScanThema)
AND b.intBedrijfID In (SELECT intBedrijfID FROM tblTempPortefScan)
AND o.strOordeel="SUB"
AND o.datAdded=(SELECT max(oo.datAdded) FROM tblOpinie oo WHERE oo.intBedrijfID = o.intBedrijfID AND oo.intResearchThemaID = o.intResearchThemaID)
AND iif(n.datDatum IS NULL, "1", n.datDatum)=iif(n.datDatum IS NULL, "1",  (SELECT max(nn.datDatum) FROM tblNFIAlgemeen nn WHERE nn.intBedrijfID = n.intBedrijfID))
ORDER BY t.strResearchThema, b.strBedrijfnaam;


Dit werkt als een trein, mits er niet twee opinies op dezelfde datum zijn ingevoerd. Dan worden (logisch) allebei de opinies getoond. Daarom had ik de volgende query bedacht:

SQL:
1
2
3
4
5
6
7
8
9
SELECT t.strResearchThema AS Thema, "WAAR" AS Scan, b.strBedrijfnaam AS Name_ING, o.strOpinie AS SubtekstNL, n.strNFIText
FROM tblNFIAlgemeen AS n RIGHT JOIN ((tblBedrijven AS b INNER JOIN tblOpinie AS o ON b.intBedrijfID = o.intBedrijfID) INNER JOIN tblResearchThema AS t ON o.intResearchThemaID = t.intResearchThemaID) ON n.intBedrijfID = b.intBedrijfID
WHERE o.intResearchThemaID In (SELECT intThemaID FROM tblTempPortefScanThema)
AND b.intBedrijfID In (SELECT intBedrijfID FROM tblTempPortefScan)
AND o.strOordeel="SUB"
AND o.datAdded=(SELECT max(oo.datAdded) FROM tblOpinie oo WHERE oo.intBedrijfID = o.intBedrijfID AND oo.intResearchThemaID = o.intResearchThemaID)
AND o.intOpinieID=(SELECT max(ooo.intOpinieID) FROM tblOpinie ooo WHERE ooo.intBedrijfID = o.intBedrijfID AND ooo.intResearchThemaID = o.intResearchThemaID AND ooo.datAdded = o.datAdded)
AND iif(n.datDatum IS NULL, "1", n.datDatum)=iif(n.datDatum IS NULL, "1",  (SELECT max(nn.datDatum) FROM tblNFIAlgemeen nn WHERE nn.intBedrijfID = n.intBedrijfID))
ORDER BY t.strResearchThema, b.strBedrijfnaam;


Er wordt dus een extra subquery uitgevoerd (regel 7) die van de records met de hoogste datum het record met het hoogste id pakt (het meest recent ingevoerde record dus). Deze constructie werkt maar ziet er wel tamelijk omslachtig uit. Zijn er makkelijkere (en mogelijk snellere) manieren om dit te fixen?

[ Voor 3% gewijzigd door Verwijderd op 04-07-2006 14:34 ]


  • lier
  • Registratie: Januari 2004
  • Laatst online: 09:58

lier

MikroTik nerd

Voordat ik verdrink in de lap SQL, zou je je datamodel ook even kunnen posten ?
(Dit is natuurlijk af te leiden uit je SQL, maar ik ben een beetje lui...).

Ten aanzien van optimalisatie, soms werkt het erg snel om met tijdelijke tabellen te werken. Een en ander is natuurlijk ook afhankelijk van je filesystem enzo.

Tweede punt voor optimalisatie zijn indexen. Bekijk in ieder geval even met behulp van Execution Plan hoe je tabel(len) benaderd word(en)(t).

Eerst het probleem, dan de oplossing


Verwijderd

Topicstarter
Hmm, datamodel is niet zo nuttig denk ik. Het gaat vooral om de volgende regels:

(oud)
SQL:
1
AND o.datAdded=(SELECT max(oo.datAdded) FROM tblOpinie oo WHERE oo.intBedrijfID = o.intBedrijfID AND oo.intResearchThemaID = o.intResearchThemaID)


en

(nieuw)
SQL:
1
2
AND o.datAdded=(SELECT max(oo.datAdded) FROM tblOpinie oo WHERE oo.intBedrijfID = o.intBedrijfID AND oo.intResearchThemaID = o.intResearchThemaID)
AND o.intOpinieID=(SELECT max(ooo.intOpinieID) FROM tblOpinie ooo WHERE ooo.intBedrijfID = o.intBedrijfID AND ooo.intResearchThemaID = o.intResearchThemaID AND ooo.datAdded = o.datAdded)


Ik wil dus per opinie (o) de gegevens van de meest recente o.datAdded per o.intBedrijfID en o.intResearchThemaID. Omdat er soms twee records zijn met een gelijke o.datAdded, o.intBedrijfID en o.intResearchThemaID en ik maar één record terug wil krijgen per o.intBedrijfID en o.intResearchThemaID heb ik een extra selectie op o.intOpinieID gemaakt. Het werkt, maar is er wellicht een betere manier?

  • lier
  • Registratie: Januari 2004
  • Laatst online: 09:58

lier

MikroTik nerd

Je kan natuurlijk gebruik maken van de group by in combinatie met MAX id.


Dan krijg je zoiets:

SELECT intOpinieID, datum, bedrijf FROM [tabel] WHERE intOpinieID IN
(SELECT max(intOpiniID) FROM [tabel] GROUP BY intOpiniID, bedrijf)

[ Voor 54% gewijzigd door lier op 04-07-2006 14:48 ]

Eerst het probleem, dan de oplossing


  • moozzuzz
  • Registratie: Januari 2005
  • Niet online
Waarom selecteer je niet meteen altijd het hoogste ID (zonder naar de datum te kijken)?