Kan je met SQL (in mijn geval SQLite) ook een eerder berekende waarde hergebruiken?

Voorbeeld:

SELECT
	beschrijving,
	((strftime('%s', Uren.eindTijd) - strftime('%s', Uren.startTijd)) / 3600.0) as aantal,
	aantal * Tarieven.prijsPerUur as prijs
FROM
	Uren
JOIN 
	Tarieven ON Uren.tariefId = Tarieven.id


Hier is 'aantal' het aantal uur dat ik ergens aan heb gewerkt, en deze wil ik apart op mijn factuur hebben staan. Daarnaast wil ik ook de prijs voor dat uur hebben, dat wordt berekend door het aantal uur te vermenigvuldigen met de prijsPerUur.

Maar het aantal uur heb ik al uitgerekend, ik hoef hem dus alleen nog maar te vermenigvuldigen. Echter kan ik 'aantal' niet gebruiken in mijn query (kolom niet gevonden) en ben ik bang dat ik die 'hele berekening' (het gaat om het principe) weer helemaal overnieuw moet doen.

Kan dat nu niet anders?
Bij mijn weten zul je dan met een stored procedure moeten gaan werken. Je kunt de alias namelijk niet nogmaals binnen het SELECT-gedeelte gebruiken. Je kunt er bv. wel op sorteren e.d. , maar binnen de SELECT is het niet bruikbaar. Je zult dit soort zaken dus elders moeten berekenen of meerdere keren moeten berekenen binnen dezelfde query.
Bwa, wat een tekortkoming van SQL zeg...

Maar ik zie niet in hoe stored procedures, wat eigenlijk simpel gezegd niet meer is dan het benoemen en verplaatsen van een berekening, mij hierbij kunnen helpen. Ik zal dan alsnog 2 maal de procedure aan moeten roepen, en dus is het waarschijnlijk dat de berekening alsnog 2 maal wordt uitgevoerd. Tenzij de database de resultaten cached, wat mij niet logisch lijkt.

Een andere optie is een View maken waarbij ik alle data uit de tabel Uren + deze extra kolom 'aantal' neem. Ik denk dat dat de meest nette oplossing is, al vraag ik me af of dat niet onder het kopje 'overkill' valt. Want dan wordt eerst de view gemaakt, waarbij de berekening op alle records wordt uitgevoerd terwijl ik er misschien (waarschijnlijk!) maar een paar nodig heb. Het filteren op basis van het WHERE gedeelte gebeurt immers achteraf, anders zou je niet kunnen filteren op de resultaten in de View. Ook geen goeie oplossing als het om performance gaat dus.

Kutzooi. Waarom konden programmeurs, die de hele dag werken met variabelen nu niet even een soort van variabelen maken in de SQL standaard. Ik begin serieus te twijfelen aan de onder andere door jouw zo gepropageerde 'kracht van databases' als ze al niet eens dit soort standaard-stuff kunnen.

/me wacht nog altijd op een 'native' oplossing, een oplossing waarbij het lijkt alsof je gewoon objecten in het geheugen propt en ze er op een gegeven moment in precies dezelfde vorm uit komen.
als ze al niet eens dit soort standaard-stuff kunnen
In een stored procedure gaat dat dus wél!

Daar kun je gewoon variabelen benoemen, een waarde gegeven, mee gaan rekenen, etc. etc. etc.
pgSQL kent eveneens de CURSOR: link

Zonder LOOP kun je overigens ook variabelen een waarde geven en daar wat mee gaan doen. Dat is niet iets dat specifiek aan een LOOP is gekoppeld.

Edit: Hier nog even een eenvoudig voorbeeldje:

CREATE OR REPLACE FUNCTION scripts.get_db(IN name text, OUT db text) AS
$BODY$
DECLARE
	user text = name;
BEGIN
	IF (user = 'pgFrank')
		THEN db = 'pgSQL';
	ELSEIF (user = 'Jelmer')
		THEN db = 'SQLite';
	ELSE
		db = 'MySQL';
	END IF;
RETURN;
END;
$BODY$
  LANGUAGE 'plpgsql' VOLATILE;

Je roept hem aan met

SELECT scripts.get_db('Jelmer');

Het is slechts een voorbeeldje, geen commentaar s.v.p. ;)
Hij vraagt dingen uit de DB vandaar de LOOP Frank maar je hebt gelijk. Ik weet alleen niet of SQLlite ook procedures kent.

Reageren