onze sponsors
Daar ben ik weer
nu met de volgende vraag. Ik heb een view (weer een view) waarin de resultaten staan van een vragen lijst. In die view komen o.a. 4 velden voor (Waarde1,.., Waarde4). Nu moet ik van deze velden de hoogste score bepalen. In de velden kan eventueel ook NULL staan. Het lijkt mij dat dit niet mogelijk is om in de view te bepalen, dus het wordt dan, neem ik een een SP die het restultaat van een tijdelijke tabel terug geeft. Denk ik zo.
Mijn idee is dus om de view te gebruiken en hier met een cursor doorheen te loopen om zo van elke vraag de max waarde te bepalen. Of heeft iemand hier een betere oplossing voor. Het resultaat moet in een report gebruikt worden, maar de logica voor het berekenen moet in de resultaatset staan. Dus niet bepaald worden in het rapport. Maw ik moet een kant en klare set leveren.
Bedankt maar weer.
Hoi Stephan,
UNPIVOT is voor dit geval wel een mooie optie volgens mij, wat dacht je van onderstaand voorbeeld ? :
use tempdb go
Create table score(ID int, waarde1 int, waarde2 int, waarde3 int, waarde4 int) Insert into score values(1, 8, 7, 8 , 5) Insert into score values(2, NULL, 5, NULL, 6) go
Create view vwScore as Select ID, WaardeNr, Score From (Select ID, waarde1, waarde2, waarde3, waarde4 From score) pvt UNPIVOT (Score FOR WaardeNR in (waarde1, waarde2, waarde3, waarde4)) unpvt go
Groeten, André
Hoi Stephan, Tsja, deze vier velden naast elkaar in een tabel zou ik direct "slecht ontwerp" noemen. Dit is namelijk tegen de regels van de eerste normaalvorm. Beter zou zijn ze in een aparte tabel te zetten, en dan zou je gewoon een GROUP BY en een MAX() functie kunnen gebruiken. In een view is het minder erg - zolang die view voor de eindgebruiker bedoeld is. Voor een view waar je later zelf weer verder op manipuleert gelden eigenlijk dezelfde normalisatieregels als voor tabellen. Jouw idee van een cursor is echt slecht. Cursors zijn de nummer één performance killer in SQL Server. Er zíjn wel situaties waarin je ze kan gebruiken, maar die zijn erg zeldzaam. Eigenlijk zouden cursors in Books Online moeten worden aangemerkt als "very advancced - to be used only by experts"; niet omdat ze zo ingewikkeld zijn, maar omdat alleen een expert kan inschatten wanneer er écht geen betere oplossing is. De praktijk is echter dat ze heeel veel worden gebruikt, vooral door mensen met weinig database ervaring omdat werken met een cursor heel erg lijkt op hun ervaring met 3GL of OO talen, terwijl set-based queries een heel andere manier van denken vereisen. Tenslotte ook nog een oplossing (daarvoor kom je hier, tenslotte). Twee zelfs. Als je alleen een sleutelveld en het maximum wilt hebben, dan kan je het volgende gebruiken:
<span style="font-family: monospace;">SELECT Sleutel, MAX(Waarde) AS MaxWaarde<br /> FROM (SELECT Sleutel, Waarde1 AS Waarde<br />       FROM   JouwView<br />       UNION ALL<br />       SELECT Sleutel, Waarde2 AS Waarde<br />       FROM   JouwView<br />       UNION ALL<br />       SELECT Sleutel, Waarde3 AS Waarde<br />       FROM   JouwView<br />       UNION ALL<br />       SELECT Sleutel, Waarde4 AS Waarde<br />       FROM   JouwView) AS d<br /> GROUP BY Sleutel;<br /> </span>
Als je nog meer kolommen in het resultaat wilt hebben, dan is deze constructie niet mogelijk. In dat geval zit je vast aan een tamelijk ingewikkelde CASE:
SELECT Sleutel, --andere kolommen hier toevoegen,<br />        CASE WHEN Waarde1 >= COALESCE(Waarde2, Waarde1)<br />              AND Waarde1 >= COALESCE(Waarde3, Waarde1)<br />              AND Waarde1 >= COALESCE(Waarde4, Waarde1) THEN Waarde1<br />             WHEN Waarde2 >= COALESCE(Waarde3, Waarde2)<br />              AND Waarde2 >= COALESCE(Waarde4, Waarde2) THEN Waarde2<br />             WHEN Waarde3 >= COALESCE(Waarde4, Waarde3) THEN Waarde3<br />             ELSE Waarde4<br />        END AS MaxWaarde<br /> FROM   JouwView;