A la lliçó anterior retornaves dades tal com estan desades. Però una base de dades no desa el preu amb IVA, ni el marge d'un producte, ni l'import d'una línia de comanda: desa les peces mínimes i la resta es calcula en consultar-ho. En aquesta lliçó aprendràs a construir aquestes columnes calculades amb expressions aritmètiques i de text, a posar-los un nom llegible amb AS, i a entendre —fent servir l'ordre lògic d'execució de 02-01— per què aquest nom es pot fer servir en uns llocs de la consulta i en uns altres no. Aquí apareix, a més, l'expressió més important de tot el curs: quantitat * preu_unitari * (1 - descompte).

Contingut

  1. Àlies de columna amb AS
  2. Quan l'àlies necessita cometes dobles
  3. Àlies de taula
  4. Columnes calculades: aritmètica sobre columnes
  5. L'expressió estrella: l'import d'una línia de comanda
  6. Concatenació de text: || i CONCAT
  7. ROUND per presentar diners
  8. Per què l'àlies no funciona a WHERE però sí a ORDER BY
  9. Errors habituals i consells
  10. Exercicis
  11. Conclusió

  1. Àlies de columna amb AS

Un àlies és el nom que vols que tingui una columna al resultat. Es declara amb AS:

SELECT nom AS producte,
       preu AS pvp
FROM productes;

Abans de res, comprovem per què cal. Sense àlies, una expressió no té nom:

SELECT nom, preu * 1.21
FROM productes;
nom ?column?
Oli d'oliva verge extra 500 ml 15.1250
... ...

?column? és la manera que té PostgreSQL de dir "això no té nom". Un informe amb aquesta capçalera no serveix de res, i un programa que accedeixi al resultat pel nom de la columna no hi trobarà res. Amb àlies:

SELECT nom                   AS producte,
       preu                  AS preu_sense_iva,
       preu * 1.21           AS preu_amb_iva
FROM productes;
producte preu_sense_iva preu_amb_iva
Oli d'oliva verge extra 500 ml 12.50 15.1250
Arròs integral ecològic 1 kg 3.90 4.7190
Mel de tarongina crua 500 g 9.75 11.7975
Pasta d'espelta 500 g 2.80 3.3880
Tomàquet triturat ecològic 400 g 1.95 2.3595
Crema facial d'àloe vera 50 ml 18.90 22.8690
Xampú sòlid de romaní 80 g 8.40 10.1640
Oli corporal d'ametlles 200 ml 14.25 17.2425
Bàlsam labial de calèndula 15 ml 4.60 5.5660
Detergent ecològic concentrat 1 L 11.20 13.5520

(10 primeres de 20 files.)

La paraula AS és opcional per a les columnes. Aquestes dues línies són equivalents:

SELECT preu * 1.21 AS preu_amb_iva FROM productes;
SELECT preu * 1.21    preu_amb_iva FROM productes;

Tot i així, escriu-la sempre. Sense AS, oblidar una coma converteix una columna en l'àlies de l'anterior i la consulta s'executa sense error donant un resultat equivocat (ho vas veure a 01-03 i a 02-01):

SELECT nom preu FROM productes;   -- una sola columna, anomenada "preu",
                                  -- que conté els NOMS dels productes
preu
Oli d'oliva verge extra 500 ml
...

  1. Quan l'àlies necessita cometes dobles

Un àlies és un identificador, així que segueix les regles de 01-03: sense cometes es plega a minúscules i només admet lletres, dígits i guions baixos.

Àlies Necessita cometes? Resultat
AS preu_amb_iva No Columna preu_amb_iva
AS PreuAmbIVA No, però... La columna es dirà preuambiva (plegada a minúscules)
AS "Preu amb IVA" (té espais) Columna Preu amb IVA
AS "Marge %" (té %) Columna Marge %
AS order (order és paraula reservada) Error sense cometes
AS 'Preu' Mai Error: les cometes simples són per a cadenes
SELECT nom             AS "Producte",
       preu            AS "Preu (€)",
       preu * 1.21     AS "Preu amb IVA (€)"
FROM productes;
Producte Preu (€) Preu amb IVA (€)
Te verd matcha cerimonial 30 g 22.00 26.6200
... ... ...

Aquest és l'únic ús legítim de les cometes dobles en aquest curs: àlies de presentació destinats a un informe o a una exportació. Per a qualsevol àlies que hagis de reutilitzar dins de la consulta, fes servir snake_case en minúscules i estalvia't les cometes.

Nota de dialecte: MySQL i SQLite permeten a més fer servir cometes invertides (`Preu amb IVA`) o cometes simples com a delimitador d'àlies. PostgreSQL no: cometes dobles o res. Escriu sempre la forma estàndard.

  1. Àlies de taula

També les taules admeten àlies, i aquí AS és igualment opcional:

SELECT p.id,
       p.nom,
       p.preu
FROM productes AS p;

Amb una sola taula sembla un caprici: p.nom no aporta res enfront de nom. El seu valor apareix al mòdul 3, quan una consulta combini diverses taules que tenen columnes amb el mateix nom:

-- Avanç del mòdul 3, NO ho executis encara
SELECT p.nom AS producte,
       c.nom AS categoria
FROM productes AS p
JOIN categories AS c ON p.categoria_id = c.id;

Sense els àlies p i c, nom seria ambigu i PostgreSQL respondria column reference "nom" is ambiguous. Per això, en SQL professional, gairebé totes les consultes porten àlies de taula.

Convencions útils per als àlies de taula:

Pràctica Exemple Comentari
Inicial o abreviatura curta productes AS p, linies_comanda AS lc El més estès
Nom significatiu si hi ha ambigüitat empleats AS cap, clients AS referidor Imprescindible en unir una taula amb si mateixa (03-06)
Prefixar totes les columnes si hi ha àlies p.nom, p.preu Evita sorpreses en afegir taules després
Àlies d'una sola lletra críptica productes AS x Evitar: il·legible en consultes llargues

Una diferència que sorprèn: si poses àlies a la taula, el nom original deixa d'estar disponible. Això falla:

SELECT productes.nom
FROM productes AS p;
ERROR:  invalid reference to FROM-clause entry for table "productes"
HINT:  Perhaps you meant to reference the table alias "p".

  1. Columnes calculades: aritmètica sobre columnes

Una columna calculada és una expressió a la llista del SELECT. S'avalua fila a fila, amb els valors d'aquella fila.

4.1. Marge brut

SELECT nom,
       preu,
       cost,
       preu - cost AS marge
FROM productes;
nom preu cost marge
Oli d'oliva verge extra 500 ml 12.50 7.80 4.70
Arròs integral ecològic 1 kg 3.90 2.10 1.80
Mel de tarongina crua 500 g 9.75 5.40 4.35
Pasta d'espelta 500 g 2.80 1.35 1.45
Tomàquet triturat ecològic 400 g 1.95 0.90 1.05
Crema facial d'àloe vera 50 ml 18.90 9.50 9.40
Xampú sòlid de romaní 80 g 8.40 3.60 4.80
Oli corporal d'ametlles 200 ml 14.25 7.10 7.15
Bàlsam labial de calèndula 15 ml 4.60 1.80 2.80
Detergent ecològic concentrat 1 L 11.20 6.00 5.20

(10 primeres de 20 files.)

En la resta, l'escala del resultat és la més gran de les dues, així que el marge surt amb dos decimals nets. En la multiplicació no serà així.

4.2. Marge percentual

SELECT nom,
       preu,
       cost,
       (preu - cost) / preu * 100 AS marge_pct
FROM productes;
nom preu cost marge_pct
Oli d'oliva verge extra 500 ml 12.50 7.80 37.6000000000000000
Arròs integral ecològic 1 kg 3.90 2.10 46.1538461538461538
Mel de tarongina crua 500 g 9.75 5.40 44.6153846153846154
Pasta d'espelta 500 g 2.80 1.35 51.7857142857142857
Tomàquet triturat ecològic 400 g 1.95 0.90 53.8461538461538462
Crema facial d'àloe vera 50 ml 18.90 9.50 49.7354497354497354

(6 primeres de 20 files.)

Tres coses per aprendre d'aquí:

  1. Els parèntesis són obligatoris. Sense ells, preu - cost / preu * 100 s'avaluaria com preu - ((cost / preu) * 100), perquè * i / tenen més prioritat que - (taula de precedència de 01-03). El resultat per al producte 1 seria 12.50 - 62.4 = -49.90. No dona error: dona un número absurd.
  2. La divisió és decimal, no entera, perquè preu és NUMERIC i no INTEGER. Si les columnes fossin enteres, (preu - cost) / preu donaria 0 per a totes les files i després 0 * 100 = 0. És la fallada clàssica en calcular percentatges; es resol convertint un operand a NUMERIC amb CAST (mòdul 6).
  3. La cua de decimals és lletja. PostgreSQL calcula la divisió NUMERIC amb precisió àmplia. Per presentar-ho cal ROUND (secció 7).

4.3. Altres expressions útils sobre una sola taula

SELECT nom,
       stock,
       preu,
       stock * preu AS valor_inventari_pvp,
       stock * cost AS valor_inventari_cost
FROM productes;
nom stock preu valor_inventari_pvp valor_inventari_cost
Oli d'oliva verge extra 500 ml 120 12.50 1500.00 936.00
Arròs integral ecològic 1 kg 200 3.90 780.00 420.00
Mel de tarongina crua 500 g 80 9.75 780.00 432.00
Pasta d'espelta 500 g 150 2.80 420.00 202.50
Tomàquet triturat ecològic 400 g 300 1.95 585.00 270.00
Espelmes de cera de soja (pack 2) 0 13.75 0.00 0.00

(Selecció de files de les 20.)

Aquí stock és INTEGER i preu és NUMERIC(10,2): en barrejar tipus, PostgreSQL promou l'enter a NUMERIC i el resultat conserva dos decimals.

Compte amb la divisió entre zero. Si en comptes de stock * preu calculessis alguna_cosa / stock, el producte 13 (stock 0) faria fallar la consulta sencera amb ERROR: division by zero. La protecció es fa amb NULLIF, que es veu al mòdul 6.

  1. L'expressió estrella: l'import d'una línia de comanda

A 01-06 va quedar fixat que comandes no té columna total i que l'import d'una línia és:

quantitat * preu_unitari * (1 - descompte)

Aquesta expressió apareixerà pràcticament a tots els mòduls que queden. Escrivim-la per primera vegada:

SELECT id,
       comanda_id,
       producte_id,
       quantitat,
       preu_unitari,
       descompte,
       quantitat * preu_unitari * (1 - descompte) AS import
FROM linies_comanda;
id comanda_id producte_id quantitat preu_unitari descompte import
1 1 1 2 11.95 0.00 23.9000
2 1 2 3 3.90 0.00 11.7000
3 1 14 2 3.25 0.00 6.5000
4 2 6 1 17.50 0.00 17.5000
5 2 9 2 4.60 0.00 9.2000
6 3 5 6 1.95 0.10 10.5300
7 3 4 4 2.80 0.00 11.2000
8 3 2 2 3.90 0.00 7.8000
9 4 15 1 22.00 0.00 22.0000
10 4 3 1 9.75 0.00 9.7500
11 5 10 1 11.20 0.00 11.2000
12 5 11 2 5.50 0.00 11.0000

(12 primeres de 47 files.)

Desmuntem l'expressió, perquè cada peça importa:

Tros Per què hi és
quantitat * Unitats venudes d'aquell producte en aquella comanda
preu_unitari El preu del moment de la venda, no l'actual. Per això la línia 1 fa servir 11.95 € i no els 12.50 € que avui costa el producte 1
(1 - descompte) descompte és una fracció: 0.10 = 10 %. 1 - 0.10 = 0.90, és a dir "es cobra el 90 %"
Els parèntesis Sense ells, quantitat * preu_unitari * 1 - descompte restaria 0.10 € al total en comptes d'aplicar un 10 %

Comprova la línia 6 a mà: 6 unitats × 1.95 € = 11.70 €; amb un 10 % de descompte, 11.70 × 0.90 = 10.53 €. Coincideix.

I fixa't en els quatre decimals: 10.5300, no 10.53. La quantitat és entera i no aporta escala, preu_unitari n'aporta 2 i (1 - descompte) altres 2, així que el resultat surt amb 4. Aritmèticament és correcte i per sumar és el que vols, però per ensenyar-ho a algú cal arrodonir.

Sis línies de les 47 porten descompte; aquests són els seus imports exactes:

id comanda_id quantitat preu_unitari descompte import
6 3 6 1.95 0.10 10.5300
18 8 3 12.50 0.05 35.6250
24 10 2 18.90 0.10 34.0200
27 11 8 1.95 0.15 13.2600
39 16 2 11.20 0.05 21.2800
45 19 6 4.95 0.10 26.7300

Aquí hi ha un detall revelador: la línia 24 val 34.0200 € i la devolució de la comanda 10 registrada a devolucions és de 34.02 €. Les dades són coherents entre taules, i comprovar-ho amb una consulta serà un dels exercicis del mòdul 3.

Error freqüent: escriure quantitat * preu_unitari * descompte. Això calcula l'import descomptat, no l'import cobrat. Per a la línia 6 donaria 1.17 € en comptes de 10.53 €.

  1. Concatenació de text: || i CONCAT

L'operador estàndard de concatenació en SQL és ||:

SELECT nom || ' ' || cognoms AS client,
       ciutat,
       pais
FROM clients;
client ciutat pais
Lucía Martínez Soler València Espanya
Carlos Ferrer Ibáñez València Espanya
Marta Sanchis Gil Castelló Espanya
Javier Ortega Ruiz Madrid Espanya
Ana Belmonte Roca Barcelona Espanya
Pau Llorens Vidal València Espanya
Sofia Moreira Costa Lisboa Portugal
Tiago Almeida Nunes Porto Portugal
Camille Dubois Lió França
Julien Moreau París França
Elena Navarro Puig Alacant Espanya
Diego Ramos Herrera Sevilla Espanya
Núria Bosch Ferrer Barcelona Espanya
Hugo Iglesias Pardo Saragossa Espanya
Inés Carrasco Vega València Espanya

Pots concatenar text amb números: PostgreSQL converteix el número a text automàticament.

SELECT nom,
       'Ref. ' || id || ' - ' || preu || ' EUR' AS etiqueta
FROM productes;
nom etiqueta
Oli d'oliva verge extra 500 ml Ref. 1 - 12.50 EUR
Arròs integral ecològic 1 kg Ref. 2 - 3.90 EUR
Mel de tarongina crua 500 g Ref. 3 - 9.75 EUR

(3 primeres de 20 files.)

6.1. El parany de || amb NULL

Concatenar qualsevol cosa amb NULL dona NULL. Tot el text es perd. Aquesta és una de les sorpreses més cares de SQL, i BotigaVerda té dades per demostrar-ho: set clients tenen referit_per_id a NULL.

SELECT nom,
       referit_per_id,
       'Referit pel client ' || referit_per_id AS origen
FROM clients;
nom referit_per_id origen
Lucía (null) (null)
Carlos 1 Referit pel client 1
Marta 1 Referit pel client 1
Javier (null) (null)
Ana 2 Referit pel client 2
Pau (null) (null)
Sofia (null) (null)
Tiago 7 Referit pel client 7
Camille (null) (null)
Julien 9 Referit pel client 9
Elena 6 Referit pel client 6
Diego (null) (null)
Núria 5 Referit pel client 5
Hugo (null) (null)
Inés 1 Referit pel client 1

Set files amb origen buit, no set files amb el text i un forat. El literal 'Referit pel client ' desapareix del tot, perquè la regla dels nuls és que qualsevol operació amb un valor desconegut produeix un valor desconegut.

6.2. CONCAT tracta els nuls d'una altra manera

La funció CONCAT ignora els NULL i els substitueix per una cadena buida:

SELECT nom,
       referit_per_id,
       CONCAT('Referit pel client ', referit_per_id) AS origen
FROM clients;
nom referit_per_id origen
Lucía (null) Referit pel client
Carlos 1 Referit pel client 1
Javier (null) Referit pel client
Ana 2 Referit pel client 2

(Selecció de files de les 15.)

Ja no es perd el text, però el resultat tampoc no és correcte: diu "Referit pel client" sense dir quin. La solució de debò és substituir el nul per un text sensat amb COALESCE, que s'estudia a la lliçó 06-04:

-- Avanç del mòdul 6
SELECT nom,
       COALESCE('Referit pel client ' || referit_per_id, 'Va arribar pel seu compte') AS origen
FROM clients;

Comparativa per tenir a mà:

| Aspecte | a || b | CONCAT(a, b) | |---|---|---| | Estàndard SQL | Sí | No (però molt estesa) | | Amb NULL | Retorna NULL | Tracta el NULL com a '' | | A MySQL | Per defecte no concatena: || és l'OR lògic | És la forma habitual | | A SQL Server | No existeix; es fa servir + | Existeix des del 2012 | | A SQLite | Sí | No existeix |

Nota de dialecte important: a MySQL, 'a' || 'b' retorna 0, perquè allà || significa OR. Només es comporta com a concatenació si el servidor té activat el mode PIPES_AS_CONCAT. Si escrius SQL que hagi de funcionar a MySQL i a PostgreSQL, fes servir CONCAT.

  1. ROUND per presentar diners

ROUND(expressió, decimals) arrodoneix a la quantitat de decimals que indiquis:

SELECT nom,
       preu,
       ROUND(preu * 1.21, 2)                  AS preu_amb_iva,
       ROUND((preu - cost) / preu * 100, 2)   AS marge_pct
FROM productes;
nom preu preu_amb_iva marge_pct
Oli d'oliva verge extra 500 ml 12.50 15.13 37.60
Arròs integral ecològic 1 kg 3.90 4.72 46.15
Mel de tarongina crua 500 g 9.75 11.80 44.62
Pasta d'espelta 500 g 2.80 3.39 51.79
Tomàquet triturat ecològic 400 g 1.95 2.36 53.85
Crema facial d'àloe vera 50 ml 18.90 22.87 49.74
Xampú sòlid de romaní 80 g 8.40 10.16 57.14
Oli corporal d'ametlles 200 ml 14.25 17.24 50.18
Bàlsam labial de calèndula 15 ml 4.60 5.57 60.87
Detergent ecològic concentrat 1 L 11.20 13.55 46.43
Fregall vegetal de lufa (pack 3) 5.50 6.66 60.00
Bosses reutilitzables de cotó (pack 5) 9.90 11.98 56.57
Espelmes de cera de soja (pack 2) 13.75 16.64 49.82
Infusió de camamilla ecològica 20 u 3.25 3.93 56.92
Te verd matcha cerimonial 30 g 22.00 26.62 43.18
Kombutxa de gingebre 750 ml 4.95 5.99 53.54
Suc de taronja premsat en fred 1 L 5.40 6.53 51.85
Raspall de dents de bambú 3.50 4.24 65.71
Desodorant natural en barra 50 g 7.80 9.44 57.69
Càpsules d'espirulina 120 u 16.40 19.84 46.95

Ara sí que és una taula presentable. I amb ella ja pots respondre a una pregunta de negoci: el producte amb més marge percentual és el raspall de dents de bambú (65.71 %), i el que menys, l'oli d'oliva verge extra (37.60 %) —el producte estrella del catàleg és, precisament, el que deixa menys marge relatiu.

El mateix per a l'import de línia:

SELECT id,
       comanda_id,
       ROUND(quantitat * preu_unitari * (1 - descompte), 2) AS import
FROM linies_comanda;
id comanda_id import
6 3 10.53
18 8 35.63
24 10 34.02
27 11 13.26
39 16 21.28
45 19 26.73

(Les 6 línies amb descompte, de les 47.)

Observa la línia 18: el valor exacte és 35.6250 i ROUND el deixa en 35.63. Sobre tipus NUMERIC, PostgreSQL arrodoneix "mig cap amunt" (allunyant-se del zero), que és el que espera qualsevol comptable.

Regla del curs: calcula amb l'expressió completa i arrodoneix només al final, per presentar. Si arrodoneixes cada línia i després sumes, el total pot diferir en cèntims del total arrodonit. Les funcions numèriques (ROUND, CEIL, FLOOR, TRUNC, ABS) s'estudien a fons a la lliçó 06-02.

  1. Per què l'àlies no funciona a WHERE però sí a ORDER BY

Aquí és on l'ordre lògic de 02-01 deixa de ser teoria. Intenta filtrar per una columna calculada:

SELECT nom,
       preu * 1.21 AS preu_amb_iva
FROM productes
WHERE preu_amb_iva > 20;
ERROR:  column "preu_amb_iva" does not exist
LINE 4: WHERE preu_amb_iva > 20;
              ^

La taula existeix, l'àlies està escrit just a sobre, i tot i així el motor diu que aquesta columna no existeix. L'explicació és al diagrama:

flowchart LR
    A["1 · FROM<br/>productes"] --> B["2 · WHERE<br/>❌ l'àlies encara NO existeix"]
    B --> C["3 · SELECT<br/>✅ aquí NEIX l'àlies"]
    C --> D["4 · ORDER BY<br/>✅ l'àlies ja existeix"]
    D --> E["5 · LIMIT"]

Quan s'avalua WHERE, el pas SELECT encara no s'ha executat, així que el nom preu_amb_iva encara no s'ha creat. Quan s'avalua ORDER BY, sí.

Les dues solucions per filtrar per una expressió:

-- Opció A: repetir l'expressió al WHERE (sempre funciona)
SELECT nom,
       preu * 1.21 AS preu_amb_iva
FROM productes
WHERE preu * 1.21 > 20;
nom preu_amb_iva
Crema facial d'àloe vera 50 ml 22.8690
Te verd matcha cerimonial 30 g 26.6200
-- Opció B: embolcallar la consulta en una subconsulta (mòdul 7)
SELECT nom, preu_amb_iva
FROM (SELECT nom, preu * 1.21 AS preu_amb_iva FROM productes) AS t
WHERE preu_amb_iva > 20;

I a ORDER BY l'àlies funciona sense més (lliçó 02-05):

SELECT nom,
       preu - cost AS marge
FROM productes
ORDER BY marge DESC;
nom marge
Te verd matcha cerimonial 30 g 9.50
Crema facial d'àloe vera 50 ml 9.40
Càpsules d'espirulina 120 u 7.70
Oli corporal d'ametlles 200 ml 7.15
Espelmes de cera de soja (pack 2) 6.85

(5 primeres de 20 files.)

Resum per memoritzar:

Clàusula Es pot fer servir un àlies del SELECT? Motiu
WHERE No S'executa abans que SELECT
GROUP BY Sí a PostgreSQL (extensió), no a l'estàndard Mòdul 4
HAVING No Mòdul 4
ORDER BY S'executa després de SELECT

Errors habituals i consells

  • Oblidar AS i perdre una coma. SELECT nom preu FROM productes no falla: retorna els noms sota la capçalera preu. Compta sempre les columnes del resultat.
  • Àlies amb cometes simples. AS 'Preu' és un error de sintaxi a PostgreSQL. Cometes dobles per a identificadors, simples per a cadenes.
  • Esperar que AS PreuIVA conservi les majúscules. Sense cometes es plega a preuiva.
  • Fer servir un àlies a WHERE. column "..." does not exist. Repeteix l'expressió o fes servir una subconsulta.
  • Oblidar els parèntesis al marge percentual. preu - cost / preu * 100 no dona error i retorna números sense sentit.
  • Confondre el descompte amb l'import descomptat. L'import cobrat és quantitat * preu_unitari * (1 - descompte); sense l'1 - calcules justament el contrari.
  • Concatenar amb || sobre columnes que poden ser nul·les. Perds tota la cadena. Fes servir CONCAT o, millor, COALESCE (mòdul 6).
  • Arrodonir massa aviat. Arrodoneix només a la capa de presentació; els càlculs intermedis, amb tota la precisió.
  • Consell: anomena els àlies com a columnes reals. snake_case, en minúscules, descriptius: preu_amb_iva, marge_pct, import. Els àlies "bonics" amb cometes, només per a l'informe final.
  • Consell: valida l'expressió amb SELECT sense FROM. SELECT 8 * 1.95 * (1 - 0.15); et confirma en un segon si la fórmula és la que creus.

Exercicis

Exercici 1

Escriu una consulta sobre productes que retorni, amb àlies llegibles: el nom del producte, el seu preu, el seu marge unitari en euros i el seu marge percentual arrodonit a un decimal. Explica per què els parèntesis del marge percentual són imprescindibles.

Exercici 2

Sobre empleats, construeix una única columna de text anomenada fitxa amb aquest format exacte: Cognoms, Nom (Càrrec) - Ciutat. Per exemple: Alcázar Vives, Rosa (Directora general) - València.

Exercici 3

Sobre linies_comanda, retorna l'id de la línia, la comanda a la qual pertany, l'import brut (sense aplicar descompte), l'import descomptat en euros i l'import final cobrat, els tres arrodonits a dos decimals. Comprova els teus resultats amb les sis línies que tenen descompte.

Solucions

Solució 1

SELECT nom                                     AS producte,
       preu,
       preu - cost                             AS marge_eur,
       ROUND((preu - cost) / preu * 100, 1)    AS marge_pct
FROM productes;
producte preu marge_eur marge_pct
Oli d'oliva verge extra 500 ml 12.50 4.70 37.6
Arròs integral ecològic 1 kg 3.90 1.80 46.2
Mel de tarongina crua 500 g 9.75 4.35 44.6
Pasta d'espelta 500 g 2.80 1.45 51.8
Tomàquet triturat ecològic 400 g 1.95 1.05 53.8
Crema facial d'àloe vera 50 ml 18.90 9.40 49.7
Xampú sòlid de romaní 80 g 8.40 4.80 57.1
Oli corporal d'ametlles 200 ml 14.25 7.15 50.2
Bàlsam labial de calèndula 15 ml 4.60 2.80 60.9
Detergent ecològic concentrat 1 L 11.20 5.20 46.4

(10 primeres de 20 files.)

Raonament sobre els parèntesis. La precedència d'operadors de 01-03 diu que * i / s'avaluen abans que -. Sense parèntesis, preu - cost / preu * 100 significa preu - ((cost / preu) * 100). Per al producte 1: 12.50 - ((7.80/12.50) * 100) = 12.50 - 62.40 = -49.90. Un marge negatiu de -49.90 en un producte que guanya 4.70 € per unitat. La consulta s'executa sense cap avís: és un error silenciós, el pitjor tipus.

Solució 2

SELECT cognoms || ', ' || nom || ' (' || carrec || ') - ' || ciutat AS fitxa
FROM empleats;
fitxa
Alcázar Vives, Rosa (Directora general) - València
Company Talens, Andrés (Responsable de vendes) - València
Nadal Ripoll, Beatriz (Responsable de logística) - València
Peris Blasco, Óscar (Comercial) - València
Puig Sanchis, Laia (Comercial) - Castelló
Estévez Roig, Marc (Atenció al client) - València
Salvador Mira, Irene (Operària de magatzem) - València
Vercher Lluch, Daniel (Analista de dades) - València

Raonament. S'alternen columnes i literals de text: els literals van entre cometes simples i porten a dins els espais, comes i parèntesis del format. Han sortit les 8 files completes perquè en aquesta taula cap de les quatre columnes utilitzades no és nul·la. Si ciutat ho fos —i podria ser-ho, perquè la columna admet nuls—, aquella fila retornaria NULL sencera. En una consulta destinada a producció convindria blindar-la amb COALESCE(ciutat, 'Sense assignar'), que veuràs a 06-04.

Solució 3

SELECT id,
       comanda_id,
       ROUND(quantitat * preu_unitari, 2)                      AS import_brut,
       ROUND(quantitat * preu_unitari * descompte, 2)          AS descompte_eur,
       ROUND(quantitat * preu_unitari * (1 - descompte), 2)    AS import_final
FROM linies_comanda;

Les sis línies amb descompte, de les 47 que retorna la consulta:

id comanda_id import_brut descompte_eur import_final
6 3 11.70 1.17 10.53
18 8 37.50 1.88 35.63
24 10 37.80 3.78 34.02
27 11 15.60 2.34 13.26
39 16 22.40 1.12 21.28
45 19 29.70 2.97 26.73

Raonament. Les tres columnes comparteixen la base quantitat * preu_unitari; el que canvia és què es fa amb descompte: multiplicar per descompte dona el que el client s'estalvia, multiplicar per (1 - descompte) dona el que paga. La comprovació que la fórmula és correcta és que descompte_eur + import_final = import_brut a totes les files. A la línia 18 hi ha una diferència d'un cèntim aparent (1.88 + 35.63 = 37.51 ≠ 37.50): és l'efecte d'arrodonir cada columna per separat, ja que els valors exactes són 1.8750 i 35.6250. És exactament el motiu pel qual s'arrodoneix al final i no a cada pas intermedi.

Conclusió

Ara les teves consultes no només llegeixen: calculen.

  • Un àlies amb AS dona nom a qualsevol columna o expressió; sense ell veuràs ?column?. Escriu AS sempre, encara que sigui opcional.
  • Les cometes dobles en un àlies només són necessàries si conté espais, símbols o majúscules que vulguis conservar: fes-les servir únicament per a àlies de presentació.
  • Els àlies de taula semblen superflus amb una sola taula i seran obligatoris al mòdul 3.
  • Saps construir columnes calculades: preu amb IVA, marge en euros i marge percentual, amb els parèntesis al seu lloc i sense caure en la divisió entera.
  • Domines l'expressió que sosté tot el curs: quantitat * preu_unitari * (1 - descompte), i entens per què el descompte és una fracció i per què el resultat surt amb quatre decimals.
  • Concatenes text amb || i coneixes el seu parany: qualsevol operand NULL anul·la tota la cadena. CONCAT l'evita, COALESCE (mòdul 6) el resol bé.
  • Presentes imports amb ROUND(expressió, 2), arrodonint només al final.
  • I, sobretot, entens per l'ordre lògic d'execució per què un àlies encara no existeix a WHERE i sí a ORDER BY.

A la lliçó següent, Filtrar dades amb WHERE, afegiràs el pas 2 del diagrama: deixaràs de portar les 20 files de productes o les 47 de linies_comanda i començaràs a demanar només les que compleixen una condició. Amb comparacions sobre números, text i dates, i amb AND, OR, NOT i uns parèntesis que, un cop més, marcaran la diferència entre un resultat correcte i un de silenciosament equivocat.

Curs de SQL

Mòdul 1: Introducció a SQL

Mòdul 2: Consultes bàsiques de SQL

Mòdul 3: Treballar amb múltiples taules

Mòdul 4: Filtratge avançat de dades

Mòdul 5: Manipulació de dades

Mòdul 6: Funcions avançades de SQL

Mòdul 7: Subconsultes i consultes imbricades

Mòdul 8: Índexs i optimització del rendiment

Mòdul 9: Transaccions i concurrència

Mòdul 10: Temes avançats

Mòdul 11: SQL a la pràctica

Mòdul 12: Projecte final

© Copyright 2026. Tots els drets reservats