Des de la primera lliçó del mòdul venim repetint el mateix advertiment: el conjunt de resultats no té ordre garantit. Ha arribat el moment de prendre'n el control. ORDER BY és l'única manera que una consulta retorni les files en un ordre concret, i encara que sembli la clàusula més senzilla de SQL, amaga mitja dotzena de detalls que separen una consulta que funciona per casualitat d'una que funciona sempre: què passa amb els empats, on van els nuls, per què una lletra accentuada pot aparèixer en un lloc estrany, i per què ordenar pel número de columna és una bomba de rellotgeria.

Contingut

  1. Sense ORDER BY no hi ha ordre garantit
  2. ASC i DESC
  3. Ordenar per diverses columnes i resoldre empats
  4. Ordenar per àlies, per expressió i per posició ordinal
  5. Els nuls: NULLS FIRST i NULLS LAST
  6. Ordenar text: col·lació i accents
  7. Ordenar dates
  8. ORDER BY a l'ordre lògic d'execució
  9. Errors habituals i consells
  10. Exercicis
  11. Conclusió

  1. Sense ORDER BY no hi ha ordre garantit

Fem-ho explícit d'una vegada. Aquesta consulta:

SELECT id, nom, preu FROM productes;

retorna, avui, al teu equip, els productes de l'1 al 20. I això et dona una falsa sensació de seguretat, perquè l'estàndard SQL no promet cap ordre quan no hi ha ORDER BY, i PostgreSQL tampoc. El que veus és l'ordre en què el motor va trobar les files en recórrer el fitxer de dades.

Circumstàncies reals en què aquest ordre canvia sense que tu toquis la consulta:

Situació Què passa
S'actualitza una fila amb UPDATE PostgreSQL escriu una versió nova de la fila al final de la taula; aquesta fila passa a retornar-se l'última
L'optimitzador decideix fer servir un índex Les files surten en l'ordre de l'índex, no en el físic
La taula és gran i s'activa el paral·lelisme Diversos processos llegeixen trossos diferents i lliuren resultats entrellaçats
S'executa VACUUM FULL o es reconstrueix la taula L'ordre físic canvia del tot
S'afegeix una taula amb JOIN (mòdul 3) L'ordre depèn de l'algorisme d'unió triat

Pots comprovar el primer cas tu mateix, si t'atreveixes a modificar les dades (recorda que l'script de 01-06 és idempotent i el pots recarregar):

UPDATE productes SET stock = stock WHERE id = 1;
SELECT id, nom FROM productes;

El producte 1 apareixerà ara al final de la llista. Res no ha fallat, res no avisa: simplement l'ordre mai no va estar garantit.

Regla absoluta: si l'ordre de les files importa per al teu informe, la teva aplicació o la teva paginació, escriu ORDER BY. No hi ha dreceres, no hi ha excepcions, i "és que sempre surt bé" no és cap argument.

  1. ASC i DESC

ORDER BY s'escriu al final de la consulta i indica per quina columna ordenar i en quin sentit:

SELECT id, nom, preu
FROM productes
ORDER BY preu DESC;
id nom preu
15 Te verd matcha cerimonial 30 g 22.00
6 Crema facial d'àloe vera 50 ml 18.90
20 Càpsules d'espirulina 120 u 16.40
8 Oli corporal d'ametlles 200 ml 14.25
13 Espelmes de cera de soja (pack 2) 13.75
1 Oli d'oliva verge extra 500 ml 12.50
10 Detergent ecològic concentrat 1 L 11.20
12 Bosses reutilitzables de cotó (pack 5) 9.90
3 Mel de tarongina crua 500 g 9.75
7 Xampú sòlid de romaní 80 g 8.40
19 Desodorant natural en barra 50 g 7.80
11 Fregall vegetal de lufa (pack 3) 5.50
17 Suc de taronja premsat en fred 1 L 5.40
16 Kombutxa de gingebre 750 ml 4.95
9 Bàlsam labial de calèndula 15 ml 4.60
2 Arròs integral ecològic 1 kg 3.90
18 Raspall de dents de bambú 3.50
14 Infusió de camamilla ecològica 20 u 3.25
4 Pasta d'espelta 500 g 2.80
5 Tomàquet triturat ecològic 400 g 1.95

El catàleg complet de més car a més barat. Ja tens aquí una resposta de negoci: el matcha és el producte més car (22.00 €) i el tomàquet triturat el més barat (1.95 €).

Paraula clau Significat És el valor per defecte?
ASC Ascendent: de menor a major, d'A a Z, de data antiga a recent
DESC Descendent: al revés No

Com que ASC és el valor per defecte, aquestes dues són idèntiques:

ORDER BY preu;
ORDER BY preu ASC;

Escriure ASC explícitament no és obligatori, però en consultes amb diverses columnes i sentits barrejats ajuda molt a la lectura.

  1. Ordenar per diverses columnes i resoldre empats

Quan dues files tenen el mateix valor a la columna d'ordenació, el seu ordre relatiu no està definit. És el mateix problema de la secció 1, en petit.

SELECT id, nom, categoria_id, preu
FROM productes
ORDER BY categoria_id;

Les cinc files de la categoria 1 surten juntes, sí, però en quin ordre entre elles? El que el motor tingui a bé. Per fixar-lo s'afegeixen més columnes a l'ORDER BY, separades per comes: la segona desempata la primera, la tercera desempata la segona, i així successivament. Cada columna pot portar el seu propi ASC o DESC.

SELECT id, nom, categoria_id, preu
FROM productes
ORDER BY categoria_id ASC, preu DESC;
id nom categoria_id preu
1 Oli d'oliva verge extra 500 ml 1 12.50
3 Mel de tarongina crua 500 g 1 9.75
2 Arròs integral ecològic 1 kg 1 3.90
4 Pasta d'espelta 500 g 1 2.80
5 Tomàquet triturat ecològic 400 g 1 1.95
6 Crema facial d'àloe vera 50 ml 2 18.90
8 Oli corporal d'ametlles 200 ml 2 14.25
7 Xampú sòlid de romaní 80 g 2 8.40
9 Bàlsam labial de calèndula 15 ml 2 4.60
13 Espelmes de cera de soja (pack 2) 3 13.75
10 Detergent ecològic concentrat 1 L 3 11.20
12 Bosses reutilitzables de cotó (pack 5) 3 9.90
11 Fregall vegetal de lufa (pack 3) 3 5.50
15 Te verd matcha cerimonial 30 g 4 22.00
17 Suc de taronja premsat en fred 1 L 4 5.40
16 Kombutxa de gingebre 750 ml 4 4.95
14 Infusió de camamilla ecològica 20 u 4 3.25
19 Desodorant natural en barra 50 g 5 7.80
18 Raspall de dents de bambú 5 3.50
20 Càpsules d'espirulina 120 u 6 16.40

Un catàleg perfectament presentable: agrupat per categoria i, dins de cadascuna, de l'article més car al més barat.

Tres columnes, amb dades de clients:

SELECT id, nom, cognoms, ciutat, pais
FROM clients
ORDER BY pais, ciutat, cognoms;
id nom cognoms ciutat pais
11 Elena Navarro Puig Alacant Espanya
5 Ana Belmonte Roca Barcelona Espanya
13 Núria Bosch Ferrer Barcelona Espanya
3 Marta Sanchis Gil Castelló Espanya
4 Javier Ortega Ruiz Madrid Espanya
14 Hugo Iglesias Pardo Saragossa Espanya
12 Diego Ramos Herrera Sevilla Espanya
15 Inés Carrasco Vega València Espanya
2 Carlos Ferrer Ibáñez València Espanya
6 Pau Llorens Vidal València Espanya
1 Lucía Martínez Soler València Espanya
9 Camille Dubois Lió França
10 Julien Moreau París França
7 Sofia Moreira Costa Lisboa Portugal
8 Tiago Almeida Nunes Porto Portugal

Llegeix-ho de fora cap endins: primer tots els espanyols, dins d'ells les ciutats en ordre alfabètic, i dins de cada ciutat els cognoms. Els dos clients de Barcelona queden ordenats per cognom (Belmonte abans que Bosch) i els quatre de València també (Carrasco, Ferrer, Llorens, Martínez).

Consell professional: acaba sempre l'ORDER BY amb una columna única. Afegir , id com a últim criteri garanteix que l'ordre sigui determinista: la mateixa consulta retorna exactament el mateix ordre avui i d'aquí a un any. És imprescindible per a la paginació, que veuràs a 02-06, i perquè les proves automatitzades no fallin aleatòriament.

  1. Ordenar per àlies, per expressió i per posició ordinal

4.1. Per àlies

Aquí es cobra el deute de 02-02: com que ORDER BY s'executa després de SELECT, l'àlies ja existeix i es pot fer servir.

SELECT nom,
       preu,
       cost,
       preu - cost AS marge
FROM productes
ORDER BY marge DESC, id;
nom preu cost marge
Te verd matcha cerimonial 30 g 22.00 12.50 9.50
Crema facial d'àloe vera 50 ml 18.90 9.50 9.40
Càpsules d'espirulina 120 u 16.40 8.70 7.70
Oli corporal d'ametlles 200 ml 14.25 7.10 7.15
Espelmes de cera de soja (pack 2) 13.75 6.90 6.85
Bosses reutilitzables de cotó (pack 5) 9.90 4.30 5.60
Detergent ecològic concentrat 1 L 11.20 6.00 5.20
Xampú sòlid de romaní 80 g 8.40 3.60 4.80
Oli d'oliva verge extra 500 ml 12.50 7.80 4.70
Desodorant natural en barra 50 g 7.80 3.30 4.50
Mel de tarongina crua 500 g 9.75 5.40 4.35
Fregall vegetal de lufa (pack 3) 5.50 2.20 3.30
Bàlsam labial de calèndula 15 ml 4.60 1.80 2.80
Suc de taronja premsat en fred 1 L 5.40 2.60 2.80
Kombutxa de gingebre 750 ml 4.95 2.30 2.65
Raspall de dents de bambú 3.50 1.20 2.30
Infusió de camamilla ecològica 20 u 3.25 1.40 1.85
Arròs integral ecològic 1 kg 3.90 2.10 1.80
Pasta d'espelta 500 g 2.80 1.35 1.45
Tomàquet triturat ecològic 400 g 1.95 0.90 1.05

Observa l'empat real a les files 13 i 14: el bàlsam labial (producte 9) i el suc de taronja (producte 17) deixen exactament 2.80 € de marge. El , id final és el que fa que el 9 surti abans que el 17 de manera reproduïble; sense ell, l'ordre entre tots dos seria cosa del motor.

I fixa't que hem ordenat per id sense projectar-lo. Això és perfectament legal (a diferència del que passava amb SELECT DISTINCT a 02-04): ORDER BY pot fer servir qualsevol columna de les taules del FROM, aparegui o no al resultat.

4.2. Per expressió

També pots repetir l'expressió completa en comptes de fer servir l'àlies. El resultat és idèntic:

SELECT nom, preu, cost
FROM productes
ORDER BY (preu - cost) / preu DESC, id;
nom preu cost
Raspall de dents de bambú 3.50 1.20
Bàlsam labial de calèndula 15 ml 4.60 1.80
Fregall vegetal de lufa (pack 3) 5.50 2.20
Desodorant natural en barra 50 g 7.80 3.30
Xampú sòlid de romaní 80 g 8.40 3.60

(5 primeres de 20 files.)

Aquest és el rànquing per marge percentual, no per marge absolut, i dona un resultat molt diferent: el raspall de bambú, que només deixa 2.30 € per unitat, és el producte que més percentatge de marge aporta (65.7 %). Ordenar per la mètrica correcta importa tant com calcular-la bé.

4.3. Per posició ordinal

SQL permet ordenar pel número de columna dins del SELECT:

SELECT nom, preu
FROM productes
ORDER BY 2 DESC;

Equival a ORDER BY preu DESC, perquè preu és la segona columna de la llista.

Funciona, és estàndard i està molt estès en consultes ràpides i exploratòries. Però és fràgil i no ha d'arribar a codi que es desi:

Risc Escenari
Algú afegeix una columna al principi del SELECT ORDER BY 2 passa a ordenar per una altra cosa, sense error
Algú reordena la llista de columnes Igual
Qui llegeixi la consulta Ha de comptar columnes per entendre què fa
Combinat amb SELECT * El significat depèn de la definició de la taula, que pot canviar

Regla del curs: ORDER BY 2 per explorar a psql; nom de columna o àlies en qualsevol consulta que vulguis desar.

Un matís que sorprèn: l'ordinal només funciona a ORDER BY (i a GROUP BY, mòdul 4). A WHERE no significa res, i ORDER BY 2 + 1 no ordena per la tercera columna: PostgreSQL entén que allà hi ha una expressió constant (el número 3) i la ignora com a criteri d'ordenació, perquè val el mateix a totes les files.

  1. Els nuls: NULLS FIRST i NULLS LAST

Un NULL no és més gran ni més petit que res: és desconegut. Però per ordenar cal col·locar-lo en algun lloc, així que cada motor pren una decisió arbitrària. PostgreSQL considera que NULL és el valor més gran.

D'aquí en surten els seus valors per defecte:

Sentit On van els nuls a PostgreSQL
ASC Al final (equival a NULLS LAST)
DESC Al principi (equival a NULLS FIRST)

Vegem-ho amb comandes.empleat_id, que és NULL a les deu comandes que van entrar per la web:

SELECT id, client_id, empleat_id, estat
FROM comandes
ORDER BY empleat_id, id;
id client_id empleat_id estat
2 2 4 lliurat
6 5 4 cancellat
10 9 4 lliurat
16 4 4 enviat
4 4 5 lliurat
8 7 5 lliurat
12 10 5 lliurat
18 5 5 pagat
14 12 6 lliurat
20 9 6 pendent
1 1 (null) lliurat
3 3 (null) lliurat
5 1 (null) lliurat
7 6 (null) lliurat
9 8 (null) lliurat
11 2 (null) lliurat
13 11 (null) lliurat
15 1 (null) lliurat
17 7 (null) enviat
19 6 (null) lliurat

Les deu comandes gestionades per comercials (4, 5 i 6) primer, i les deu comandes web al final. Si vols els nuls a dalt, ho demanes explícitament:

SELECT id, client_id, empleat_id
FROM comandes
ORDER BY empleat_id NULLS FIRST, id;

Ara les comandes 1, 3, 5, 7, 9, 11, 13, 15, 17 i 19 encapçalen la llista, seguides per les del comercial 4, després el 5 i després el 6.

El mateix amb clients.referit_per_id:

SELECT id, nom, cognoms, referit_per_id
FROM clients
ORDER BY referit_per_id NULLS FIRST, id;
id nom cognoms referit_per_id
1 Lucía Martínez Soler (null)
4 Javier Ortega Ruiz (null)
6 Pau Llorens Vidal (null)
7 Sofia Moreira Costa (null)
9 Camille Dubois (null)
12 Diego Ramos Herrera (null)
14 Hugo Iglesias Pardo (null)
2 Carlos Ferrer Ibáñez 1
3 Marta Sanchis Gil 1
15 Inés Carrasco Vega 1
5 Ana Belmonte Roca 2
13 Núria Bosch Ferrer 5
11 Elena Navarro Puig 6
8 Tiago Almeida Nunes 7
10 Julien Moreau 9

Els set clients que van arribar pel seu compte a dalt, i a sota els vuit que van venir per recomanació, agrupats per qui els va portar: la Lucía n'ha portat tres (el Carlos, la Marta i la Inés), cosa que la converteix en la millor prescriptora de BotigaVerda.

5.1. Comparativa entre motors

Aquesta és una de les diferències de dialecte que més maldecaps dona en migrar consultes:

Motor NULL es considera ORDER BY col ASC ORDER BY col DESC Admet NULLS FIRST/LAST?
PostgreSQL El més gran Nuls al final Nuls al principi
Oracle El més gran Nuls al final Nuls al principi
MySQL / MariaDB El més petit Nuls al principi Nuls al final No
SQLite El més petit Nuls al principi Nuls al final Sí (des de 3.30)
SQL Server El més petit Nuls al principi Nuls al final No

És a dir: la mateixa consulta ORDER BY empleat_id posa les deu comandes web al final a PostgreSQL i al principi a MySQL. Si el teu informe mostra les deu primeres files, veuràs dades completament diferents.

Als motors que no admeten NULLS FIRST/LAST s'emula amb una columna auxiliar d'ordenació, aprofitant que un booleà ordena false abans que true:

-- Portable a MySQL i SQL Server: nuls al final encara que sigui ASC
ORDER BY (empleat_id IS NULL), empleat_id;

L'expressió empleat_id IS NULL val false (0) per a les files amb valor i true (1) per a les nul·les, així que ordenar-hi empeny els nuls al final. És un truc que convé tenir a la butxaca.

  1. Ordenar text: col·lació i accents

Ordenar números o dates és aritmètica. Ordenar text és cultura, i aquí les coses es posen interessants.

Una col·lació (collation) és el conjunt de regles que decideix si 'Àlber' va abans o després de 'Bosc', si 'cafè' i 'CAFE' es consideren iguals en ordenar, i si la ç compta com una c o com una lletra a part. Cada base de dades PostgreSQL es crea amb una col·lació per defecte, que pots consultar:

botigaverda=> SHOW lc_collate;

Els dos escenaris habituals:

Col·lació Com ordena Efecte sobre els accents i la ç
C o POSIX Per valor de byte en UTF-8 Les majúscules van abans que totes les minúscules, i les lletres accentuades i la ç van després de tota la A-Z. Àlber acaba després de Zulema
ca_ES.UTF-8, en_US.UTF-8, ICU Regles lingüístiques La À s'ordena com una A i la ç com una c; els accents només desempaten; les majúscules s'intercalen amb les minúscules

Ho pots comprovar a la teva instal·lació amb una comparació directa:

SELECT 'Àlber' < 'Bosc'                               AS collacio_de_la_base,
       ('Àlber' COLLATE "C") < ('Bosc' COLLATE "C")   AS collacio_c;

En una base creada amb col·lació lingüística (l'habitual):

collacio_de_la_base collacio_c
true false

'Àlber' < 'Bosc' és cert amb regles lingüístiques —la À es tracta com una A, i la A va abans que la B— i fals amb la col·lació C, perquè en UTF-8 la À es codifica amb dos bytes que comencen per 0xC3, molt per damunt del 0x42 de la B. La mateixa consulta, dos ordres diferents, segons com s'hagi creat la base de dades.

Per forçar una col·lació concreta en una consulta:

SELECT id, nom, cognoms, ciutat
FROM clients
ORDER BY cognoms COLLATE "ca-ES-x-icu";
id nom cognoms ciutat
8 Tiago Almeida Nunes Porto
5 Ana Belmonte Roca Barcelona
13 Núria Bosch Ferrer Barcelona
15 Inés Carrasco Vega València
9 Camille Dubois Lió
2 Carlos Ferrer Ibáñez València
14 Hugo Iglesias Pardo Saragossa
6 Pau Llorens Vidal València
1 Lucía Martínez Soler València
10 Julien Moreau París
7 Sofia Moreira Costa Lisboa
11 Elena Navarro Puig Alacant
4 Javier Ortega Ruiz Madrid
12 Diego Ramos Herrera Sevilla
3 Marta Sanchis Gil Castelló

COLLATE "ca-ES-x-icu" aplica les regles del català segons la biblioteca ICU, que PostgreSQL inclou des de la versió 10. Fixa't en Moreau abans que Moreira: comparteixen More, i després la a va abans que la i.

Pots veure les col·lacions disponibles al teu servidor amb:

botigaverda=> \dOS

Notes pràctiques sobre col·lacions:

  • La col·lació afecta també WHERE, LIKE i els índexs. Un índex creat amb una col·lació no serveix per ordenar amb una altra (mòdul 8).
  • Ordenar amb COLLATE explícit és més lent que fer servir la col·lació per defecte, perquè impedeix reutilitzar l'índex.
  • Canviar la col·lació d'una base existent és una operació major: cal reconstruir tots els índexs de text. És una decisió que es pren en crear la base de dades.
  • Si necessites un ordre "sense accents ni majúscules", la via moderna a PostgreSQL són les col·lacions no deterministes (CREATE COLLATION ... deterministic = false); la via clàssica és ordenar per LOWER(unaccent(columna)), amb funcions del mòdul 6.

  1. Ordenar dates

Les dates ordenen cronològicament, sense sorpreses, perquè el tipus DATE és un número per dins:

SELECT id, client_id, data_comanda, estat, despeses_enviament
FROM comandes
ORDER BY data_comanda DESC;
id client_id data_comanda estat despeses_enviament
20 9 2026-02-21 pendent 12.50
19 6 2026-02-09 pagat 4.95
18 5 2026-01-27 pagat 4.95
17 7 2026-01-13 enviat 9.90
16 4 2025-12-19 enviat 4.95
15 1 2025-12-02 lliurat 0.00
14 12 2025-11-14 lliurat 4.95
13 11 2025-10-22 lliurat 4.95
12 10 2025-10-01 lliurat 12.50
11 2 2025-09-09 lliurat 0.00

(10 primeres de 20 files.)

Les comandes de la més recent a la més antiga: l'ordre natural de qualsevol safata de treball. En aquest conjunt de dades la data creix amb l'id, així que ordenar per data descendent coincideix amb ordenar per id descendent; en una base real això no ha de complir-se per força (una comanda es pot gravar amb data retroactiva) i confiar-hi seria un error.

Avís important: això funciona perquè les columnes són de tipus DATE. Si una data estigués desada com a text, l'ordre seria alfabètic:

Format desat com a text Ordre alfabètic resultant
'2026-01-13' (ISO) Coincideix amb el cronològic, per casualitat afortunada
'13/01/2026' (europeu) Desastrós: el 13 de gener del 2026 aniria al costat del 13 de març del 1998

És una raó més per desar les dates en columnes de tipus data, com es va decidir a 01-04 i 01-06.

  1. ORDER BY a l'ordre lògic d'execució

ORDER BY és el penúltim pas: s'executa després que les files estiguin filtrades, projectades i deduplicades, i només LIMIT ve després.

flowchart LR
    A["1 · FROM"] --> B["2 · WHERE"]
    B --> C["3 · SELECT<br/>neixen els àlies"]
    C --> D["3b · DISTINCT"]
    D --> E["4 · ORDER BY<br/>✅ pot fer servir àlies<br/>✅ i columnes no projectades"]
    E --> F["5 · LIMIT<br/>(02-06)"]

Conseqüències que ja has vist en acció:

Pot ORDER BY... Resposta Per què
Fer servir un àlies del SELECT? L'àlies ja existeix: SELECT s'ha executat abans
Fer servir una columna que no és al SELECT? (llevat que hi hagi DISTINCT) Les columnes de la taula continuen disponibles
Fer servir una expressió calculada? S'avalua sobre les files del resultat
Fer servir l'ordinal de columna? És una comoditat de l'estàndard
Fer servir un àlies amb SELECT DISTINCT sobre una altra columna? No Restricció vista a 02-04

I una consideració de rendiment que reprendràs al mòdul 8: ordenar costa. PostgreSQL pot evitar la feina si existeix un índex que ja retorna les files en l'ordre demanat; si no, ha d'ordenar tot el conjunt a la memòria (o al disc, si no hi cap). Un ORDER BY sobre una taula de milions de files sense índex adequat és una de les causes més freqüents de consultes lentes.

Un últim apunt: si una consulta amb ORDER BY es fa servir com a subconsulta (mòdul 7) o dins d'una vista (mòdul 10), aquest ordre no es propaga necessàriament a la consulta exterior. L'ORDER BY que mana és el del nivell més extern.

Errors habituals i consells

  • Confiar en l'ordre sense ORDER BY. Funciona fins al dia que no. És l'error més car d'aquesta lliçó.
  • Oblidar el desempat. Dues files amb el mateix valor poden sortir en qualsevol ordre, i aquest ordre pot canviar entre execucions. Acaba sempre amb una columna única.
  • Posar DESC una sola vegada creient que afecta tota la llista. ORDER BY a, b DESC ordena a ascendent i b descendent. Si vols les dues descendents: ORDER BY a DESC, b DESC.
  • Ordenar per ordinal en codi de producció. ORDER BY 2 es trenca en silenci quan algú reordena el SELECT.
  • Suposar que els nuls van on tu creus. PostgreSQL els posa al final en ASC; MySQL, al principi. Si importa, escriu NULLS FIRST o NULLS LAST.
  • Ordenar dates desades com a text. Ordre alfabètic, no cronològic. Fes servir el tipus DATE.
  • Ordenar números desats com a text. '10' < '9' és cert alfabèticament. Mateix problema.
  • Sorprendre's del lloc dels accents o de la ç. Depèn de la col·lació de la base. Comprova-la amb SHOW lc_collate;.
  • Consell: fes servir COLLATE només quan de debò calgui, perquè impedeix aprofitar els índexs.
  • Consell: per als informes, ordena per allò que el lector busca. Un llistat de productes s'ordena per nom si en van a buscar un de concret, i per preu si van a comparar.
  • Consell: comprova l'ordre amb els extrems. Mira la primera i l'última fila: solen delatar de seguida un ASC/DESC invertit o uns nuls mal col·locats.

Exercicis

Exercici 1

Direcció vol el llistat del catàleg tal com apareixerà al web: només productes actius, agrupats per categoria de menor a major, i dins de cada categoria per nom alfabètic. Mostra categoria_id, id, nom i preu. Explica per què el resultat té 19 files.

Exercici 2

Recursos humans demana la plantilla ordenada per salari de major a menor, mostrant nom, cognoms, carrec, salari i cap_id. Afegeix el que calgui perquè l'ordre sigui determinista i respon: on apareix la Rosa Alcázar Vives i per què el seu cap_id nul no afecta l'ordre?

Exercici 3

Sobre linies_comanda, obtén les línies ordenades per import de major a menor, mostrant id, comanda_id, producte_id, quantitat i l'import arrodonit a dos decimals. Escriu la consulta de dues maneres —fent servir l'àlies i repetint l'expressió— i explica per què totes dues funcionen aquí però només una d'elles funcionaria en un WHERE.

Solucions

Solució 1

SELECT categoria_id,
       id,
       nom,
       preu
FROM productes
WHERE actiu
ORDER BY categoria_id, nom;
categoria_id id nom preu
1 2 Arròs integral ecològic 1 kg 3.90
1 3 Mel de tarongina crua 500 g 9.75
1 1 Oli d'oliva verge extra 500 ml 12.50
1 4 Pasta d'espelta 500 g 2.80
1 5 Tomàquet triturat ecològic 400 g 1.95
2 9 Bàlsam labial de calèndula 15 ml 4.60
2 6 Crema facial d'àloe vera 50 ml 18.90
2 8 Oli corporal d'ametlles 200 ml 14.25
2 7 Xampú sòlid de romaní 80 g 8.40
3 12 Bosses reutilitzables de cotó (pack 5) 9.90
3 10 Detergent ecològic concentrat 1 L 11.20
3 13 Espelmes de cera de soja (pack 2) 13.75
3 11 Fregall vegetal de lufa (pack 3) 5.50
4 14 Infusió de camamilla ecològica 20 u 3.25
4 16 Kombutxa de gingebre 750 ml 4.95
4 17 Suc de taronja premsat en fred 1 L 5.40
4 15 Te verd matcha cerimonial 30 g 22.00
5 19 Desodorant natural en barra 50 g 7.80
5 18 Raspall de dents de bambú 3.50

19 files perquè WHERE actiu descarta el producte 20 (Càpsules d'espirulina), l'únic descatalogat. I per això la categoria 6 no apareix al llistat: era el seu únic producte.

Dues observacions sobre l'ordre:

  • Dins de cada categoria, l'id ja no és creixent: la categoria 2 comença pel producte 9 perquè "Bàlsam labial" va abans alfabèticament que "Crema", "Oli" i "Xampú". És la prova que l'ordre el mana l'ORDER BY i no la taula.
  • A la categoria 1, "Oli d'oliva" va després de "Mel de tarongina" perquè la M precedeix la O, i els accents d'"Arròs" i de "Tomàquet" no hi intervenen: en una col·lació lingüística els accents només desempaten quan la resta de lletres coincideix. Si algun producte comencés per una lletra accentuada, en una base amb col·lació C apareixeria al final de tot el llistat. És l'efecte de la secció 6.

Solució 2

SELECT nom,
       cognoms,
       carrec,
       salari,
       cap_id
FROM empleats
ORDER BY salari DESC, id;
nom cognoms carrec salari cap_id
Rosa Alcázar Vives Directora general 62000.00 (null)
Andrés Company Talens Responsable de vendes 41000.00 1
Beatriz Nadal Ripoll Responsable de logística 39500.00 1
Daniel Vercher Lluch Analista de dades 35000.00 1
Óscar Peris Blasco Comercial 28500.00 2
Laia Puig Sanchis Comercial 27800.00 2
Marc Estévez Roig Atenció al client 24500.00 2
Irene Salvador Mira Operària de magatzem 22000.00 3

La Rosa Alcázar Vives apareix la primera, i no pel seu cap_id nul sinó perquè té el salari més alt (62 000 €). El seu cap_id nul no influeix gens ni mica en l'ordre, perquè aquella columna no participa en l'ORDER BY: apareix al resultat però no com a criteri d'ordenació. És una distinció important: els nuls només alteren l'ordre de les columnes per les quals ordenes.

El , id final garanteix el determinisme. En aquestes dades cap salari no es repeteix, així que avui no canvia res; el dia que es contractin dos comercials amb el mateix sou, el llistat continuarà sortint sempre igual.

Solució 3

Versió amb àlies:

SELECT id,
       comanda_id,
       producte_id,
       quantitat,
       ROUND(quantitat * preu_unitari * (1 - descompte), 2) AS import
FROM linies_comanda
ORDER BY import DESC, id;

Versió amb l'expressió repetida:

SELECT id,
       comanda_id,
       producte_id,
       quantitat,
       ROUND(quantitat * preu_unitari * (1 - descompte), 2) AS import
FROM linies_comanda
ORDER BY quantitat * preu_unitari * (1 - descompte) DESC, id;

Totes dues retornen el mateix. Les deu primeres files de les 47:

id comanda_id producte_id quantitat import
28 12 15 2 44.00
18 8 1 3 35.63
24 10 6 2 34.02
45 19 16 6 26.73
41 17 1 2 25.00
1 1 1 2 23.90
9 4 15 1 22.00
42 17 15 1 22.00
39 16 10 2 21.28
16 7 16 4 19.80

Per què totes dues funcionen aquí. ORDER BY s'executa després de SELECT, així que en aquell moment l'àlies import ja existeix i l'expressió també es pot reavaluar. Les dues formes són vàlides i PostgreSQL genera el mateix pla.

Per què només una funcionaria en un WHERE. WHERE s'executa abans que SELECT, així que l'àlies encara no ha nascut: WHERE import > 30 donaria column "import" does not exist. Únicament la versió amb l'expressió completa serveix per filtrar, com vas veure a 02-03. Tota aquesta lliçó es recolza en aquesta mateixa asimetria de l'ordre lògic d'execució.

Fixa't a més en l'empat de les files 7 i 8: les línies 9 i 42 valen exactament 22.00 € (una unitat de matcha en tots dos casos). El , id final és el que decideix que surti abans la 9. Sense ell, l'ordre entre totes dues seria impredictible, i un informe paginat podria arribar a mostrar la mateixa línia dues vegades o cap.

Conclusió

Ja controles l'ordre dels teus resultats:

  • Sense ORDER BY no hi ha ordre garantit. Un UPDATE, un índex o el paral·lelisme el poden canviar sense avís previ.
  • ASC (per defecte) i DESC decideixen el sentit, i cada columna de l'ORDER BY porta el seu.
  • Ordenar per diverses columnes resol els empats, i acabar amb una columna única fa l'ordre determinista: imprescindible per paginar i perquè les proves no fallin a l'atzar.
  • Pots ordenar per àlies, per expressió i per posició ordinal; aquesta última només per explorar, perquè es trenca en silenci.
  • Els nuls van al final en ASC i al principi en DESC a PostgreSQL, just al revés que a MySQL, SQLite i SQL Server. NULLS FIRST / NULLS LAST ho fa explícit.
  • L'ordre del text depèn de la col·lació de la base: amb C els accents i la ç van al final de tot; amb regles lingüístiques o ICU, al seu lloc. COLLATE "ca-ES-x-icu" força el criteri català.
  • Les dates ordenen cronològicament si —i només si— estan desades en columnes de tipus data.
  • ORDER BY és el pas 4 de l'ordre lògic: ja existeixen els àlies, encara es veuen totes les columnes, i només queda LIMIT al davant.

A l'última lliçó del mòdul, Limitar resultats amb LIMIT, afegiràs el pas 5 i tancaràs el cicle complet d'una consulta. Veuràs per què LIMIT és el primer que s'escriu en explorar una taula desconeguda, com es construeix una paginació amb OFFSET, per què aquesta paginació es degrada i es descompensa en taules grans, i què es fa en el seu lloc a les aplicacions que van de debò.

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