Salta el contingut

SELECT bàsic

Estructura d'una consulta SELECT

La instrucció SELECT recupera dades d'una o mes taules. La seva estructura bàsica és:

SELECT  [columnes o expressions]
FROM    [taula o font de dades]
WHERE   [condicions de filtratge]
ORDER BY [criteris d'ordenació]
LIMIT   [nombre màxim de files];

L'ordre d'avaluació intern del SGBD és diferent de l'ordre d'escriptura:

flowchart LR
    F["1 · FROM\ncarrega i uneix\nles taules"]
    W["2 · WHERE\nfiltra files\n(condicions de fila)"]
    G["3 · GROUP BY\nagrupa les files\nfiltrades"]
    H["4 · HAVING\nfiltra grups\n(condicions de grup)"]
    S["5 · SELECT\ncalcula expressions\ni àlies"]
    O["6 · ORDER BY\nordena el resultat"]
    L["7 · LIMIT\ntalla el nombre\nde files"]

    F --> W --> G --> H --> S --> O --> L

    style F fill:#1565c0,stroke:#0d47a1,color:#fff
    style W fill:#0277bd,stroke:#01579b,color:#fff
    style G fill:#00695c,stroke:#004d40,color:#fff
    style H fill:#558b2f,stroke:#33691e,color:#fff
    style S fill:#e65100,stroke:#bf360c,color:#fff
    style O fill:#6a1b9a,stroke:#4a148c,color:#fff
    style L fill:#b71c1c,stroke:#7f0000,color:#fff

Conèixer aquest ordre és important per entendre per que certes expressions són valides o no en certes clàusules. Per exemple: no podeu usar un àlies definit al SELECT dins del WHERE (el SGBD processa el WHERE abans de calcular els àlies), però sí podeu usar-lo al ORDER BY.


La clàusula SELECT

Seleccionar totes les columnes

SELECT * FROM clients;

Eviteu SELECT * en producció

SELECT * és convenient per explorar dades, però en aplicacions reals és una mala pràctica: recupera més dades de les necessàries, pot ser molt lent, i si l'esquema canvia (s'afegeix o elimina una columna), el comportament de l'aplicació pot canviar de forma inesperada.

Seleccionar columnes específiques (projecció)

SELECT nom, cognoms, email FROM clients;

Àlies de columnes (AS)

Els àlies permeten donar un nom diferent a una columna o expressió en el resultat:

SELECT
    nom AS nom_client,
    cognoms AS cognoms_client,
    email,
    data_alta AS "Data d'alta"   -- Les cometes dobles permeten espais i majúscules
FROM clients;
SELECT
    nom AS nom_client,
    cognoms AS cognoms_client,
    email,
    data_alta AS "Data d'alta"
FROM clients;
SELECT
    nom AS nom_client,
    cognoms AS cognoms_client,
    email,
    data_alta AS [Data d'alta]   -- SQL Server usa claudàtors per a noms amb espais
FROM clients;
SELECT
    nom AS nom_client,
    cognoms AS cognoms_client,
    email,
    data_alta AS "Data d'alta"   -- Oracle usa cometes dobles per a noms amb espais
FROM clients;

Expressions calculades

El SELECT pot contenir expressions calculades, no només noms de columnes:

SELECT
    nom || ' ' || cognoms AS nom_complet,       -- Concatenació
    UPPER(email) AS email_majuscules,
    preu * 1.21 AS preu_amb_iva,
    DATE_PART('year', AGE(data_naixement)) AS edat
FROM clients;
SELECT
    CONCAT(nom, ' ', cognoms) AS nom_complet,   -- MySQL usa CONCAT()
    UPPER(email) AS email_majuscules,
    preu * 1.21 AS preu_amb_iva,
    TIMESTAMPDIFF(YEAR, data_naixement, CURDATE()) AS edat
FROM clients;
SELECT
    nom + ' ' + cognoms AS nom_complet,          -- SQL Server usa + per concatenar
    UPPER(email) AS email_majuscules,
    preu * 1.21 AS preu_amb_iva,
    DATEDIFF(YEAR, data_naixement, GETDATE()) AS edat
FROM clients;
SELECT
    nom || ' ' || cognoms AS nom_complet,        -- Oracle usa || per concatenar
    UPPER(email) AS email_majuscules,
    preu * 1.21 AS preu_amb_iva,
    FLOOR(MONTHS_BETWEEN(SYSDATE, data_naixement) / 12) AS edat
FROM clients;

La clàusula FROM

La clàusula FROM especifica la font de dades. En el cas més simple, és el nom d'una taula.

Àlies de taules

Els àlies de taules són especialment útils en consultes amb múltiples taules per escurçar els noms i evitar ambigüitats:

SELECT c.nom, c.email, co.id_comanda, co.data_com
FROM clients c
JOIN comandes co ON c.id_client = co.id_client;

L'àlies de taula es defineix just després del nom de la taula (sense AS, tot i que és pot usar).


La clàusula WHERE

La clàusula WHERE filtra les files retornades. Nomes s'inclouen les files per a les quals la condició és TRUE.

SELECT * FROM clients WHERE actiu = TRUE;

-- Multiple conditions
SELECT * FROM productes WHERE preu > 10.00 AND estoc > 0;

-- Negation
SELECT * FROM clients WHERE NOT actiu;

Operadors de comparació

Operador Significat Exemple
= Igual WHERE estat = 'actiu'
<> o != Diferent WHERE pais <> 'ES'
<, <=, >, >= Comparació numèrica/data WHERE preu > 100
BETWEEN a AND b Rang inclusiu WHERE preu BETWEEN 10 AND 100
IN (val1, val2, ...) En una llista WHERE estat IN ('pendent', 'confirmada')
LIKE Patró de text WHERE nom LIKE 'Jo%'
IS NULL Valor absent WHERE telefon IS NULL
IS NOT NULL Valor present WHERE email IS NOT NULL

El LIKE i els seus wildcards

  • %: Qualsevol seqüència de caràcters (inclòs cap caràcter).
  • _: Exactament un caràcter qualsevol.
WHERE nom LIKE 'Jo%'          -- Comença per "Jo"
WHERE nom LIKE '%garcia%'     -- Conté "garcia" en qualsevol posició
WHERE nom LIKE '_oan'         -- Exactament 4 caràcters, acaba en "oan"
WHERE nom LIKE '___%'         -- Mínim 3 caràcters

LIKE i rendiment

El patró LIKE '%text%' (percentatge al principi) no pot usar un índex B-tree i fa un full table scan. Si necessiteu cerques de text complet eficients, considereu usar ILIKE (PostgreSQL, insensible a majúscules) amb pg_trgm, o FULLTEXT índex (MySQL), o eines especialitzades com Elasticsearch.


DISTINCT

DISTINCT elimina les files duplicades del resultat:

-- Llista de poblacions dels clients (sense duplicats)
SELECT DISTINCT poblacio FROM clients ORDER BY poblacio;

-- DISTINCT sobre múltiples columnes
SELECT DISTINCT categoria, subcategoria FROM productes ORDER BY categoria, subcategoria;
SELECT DISTINCT poblacio FROM clients ORDER BY poblacio;
SELECT DISTINCT poblacio FROM clients ORDER BY poblacio;
SELECT DISTINCT poblacio FROM clients ORDER BY poblacio;

AC0372/04/01 — Miniactivitat

RA4 · CA4.1, CA4.2, CA4.6

Usant la base de dades creada a PR0303, escriviu consultes per a:

  1. Llista completa de tots els usuaris (nom complet en una sola columna, email).
  2. Totes les instal·lacions actives amb el seu preu per hora.
  3. Les reserves de l'usuari amb id_usuari = 1.
  4. Tots els estats de reserves distints que existeixen.
  5. Instal·lacions amb preu per hora entre 10 i 30 euros.