sql >> Databasteknik >  >> RDS >> Mysql

Hur man arbetar med MySQL Subqueries

En underfråga är en SQL-fråga (Structured Query Language) som är kapslad i en annan SQL-fråga. Kommandot som underfrågan är kapslad i kallas den överordnade frågan. Underfrågor används för att förbehandla data som används i den överordnade frågan. Underfrågor kan tillämpas i SELECT , INSERT , UPDATE och DELETE operationer.

När undersökningar exekveras, bearbetas underfrågan först före den överordnade frågan. När du bygger MySQL-applikationer ger det flera fördelar att använda underfrågor:

  • De delar upp SQL-satserna i enkla logiska enheter, vilket kan göra dem lättare att förstå och underhålla. Med andra ord hjälper underfrågor att isolera komplexa delar av frågor.
  • De eliminerar behovet av att använda komplexaUNION uttalanden och JOIN uttalanden.
  • De används för att upprätthålla referensintegritet i ett scenario där främmande nycklar inte implementeras.
  • De hjälper utvecklare att koda in affärslogik i MySQL-frågor.

I den här guiden kommer du att lära dig:

  • Hur man använder en korrelerad underfråga
  • Hur man använder en korrelerad underfråga i en jämförelseoperator
  • Hur man använder en underfråga som en härledd tabell

Innan du börjar

För att följa med i den här guiden, se till att du har följande:

  1. Om du inte redan har gjort det, skapa ett Linode-konto och Compute Instance. Se våra guider Komma igång med Linode och Skapa en beräkningsinstans.

  2. Följ vår guide för att ställa in och säkra en beräkningsinstans för att uppdatera ditt system. Du kanske också vill ställa in tidszonen, konfigurera ditt värdnamn, skapa ett begränsat användarkonto och förstärka SSH-åtkomsten.

  3. MySQL-servermjukvaran (eller MariaDB) installerad på din Linode. Se avsnittet MySQL, som innehåller guider som beskriver hur du installerar MySQL på flera Linux-distributioner.

Konfigurera databasen

För att förstå hur underfrågor fungerar, skapa en exempeldatabas först. Denna exempeldatabas används för att köra de olika exempelfrågorna i den här guiden:

  1. SSH till din server och logga in på MySQL som root:

     mysql -u root -p
    

    När du uppmanas, ange root-lösenordet för din MySQL-server och tryck på Retur att fortsätta. Observera att din MySQL-servers root-lösenord inte är detsamma som root-lösenordet för din Linode.

    Obs

    Om ditt lösenord inte accepteras kan du behöva köra det föregående kommandot med sudo :

    sudo mysql -u root -p
    
  2. Om ditt lösenord accepteras bör du se MySQL-prompten:

    
    mysql >
    
    Obs

    Om du använder MariaDB kan du se en prompt som följande istället:

    
    MariaDB [(none)]>
    
  3. För att skapa en exempeldatabas med namnet test_db , kör:

    CREATE DATABASE test_db;
    

    Du bör se denna utdata, som bekräftar att databasen skapades framgångsrikt:

    
    Query OK, 1 row affected (0.01 sec)
    
  4. Byt till test_db databas:

    USE test_db;
    

    Du bör se denna utdata:

    
    Database changed
    
  5. Du har skapat test_db och valde den. Skapa sedan en tabell med namnet customers :

     CREATE TABLE customers
     (
     customer_id BIGINT PRIMARY KEY AUTO_INCREMENT,
     customer_name VARCHAR(50)
     ) ENGINE = InnoDB;
    

    Du bör se denna utdata:

    
    Query OK, 0 rows affected (0.03 sec)
    
  6. Lägg till några poster till customers tabell. Kör nedanstående INSERT kommandon ett efter ett:

    INSERT INTO customers(customer_name) VALUES ('JOHN PAUL');
    INSERT INTO customers(customer_name) VALUES ('PETER DOE');
    INSERT INTO customers(customer_name) VALUES ('MARY DOE');
    INSERT INTO customers(customer_name) VALUES ('CHRISTINE JAMES');
    INSERT INTO customers(customer_name) VALUES ('MARK WELL');
    INSERT INTO customers(customer_name) VALUES ('FRANK BRIAN');
    

    Denna utdata visas efter att varje post har infogats:

    
    Query OK, 1 row affected (0.00 sec)
    ...
    
  7. Verifiera att kundens information har infogats i databasen. Kör denna SELECT kommando:

    SELECT * FROM customers;
    

    Du bör se den här listan över kunder:

    
    +-------------+-----------------+
    | customer_id | customer_name   |
    +-------------+-----------------+
    |           1 | JOHN PAUL       |
    |           2 | PETER DOE       |
    |           3 | MARY DOE        |
    |           4 | CHRISTINE JAMES |
    |           5 | MARK WELL       |
    |           6 | FRANK BRIAN     |
    +-------------+-----------------+
    6 rows in set (0.00 sec)
    
  8. Skapa en sales tabell. Den här tabellen använder kolumnen customer_id för att referera till customers tabell:

    CREATE TABLE sales
    (
    order_id BIGINT PRIMARY KEY AUTO_INCREMENT,
    customer_id BIGINT,
    sales_amount DECIMAL(17,2)
    ) ENGINE = InnoDB;
    

    Denna utdata visas:

    
    Query OK, 0 rows affected (0.03 sec)
    
  9. Fyll sedan i sales tabell med några poster. Kör nedanstående INSERT kommandon ett efter ett:

    INSERT INTO sales (customer_id, sales_amount) VALUES ('1','25.75');
    INSERT INTO sales (customer_id, sales_amount) VALUES ('2','85.25');
    INSERT INTO sales (customer_id, sales_amount) VALUES ('5','3.25');
    INSERT INTO sales (customer_id, sales_amount) VALUES ('4','200.75');
    INSERT INTO sales (customer_id, sales_amount) VALUES ('5','88.10');
    INSERT INTO sales (customer_id, sales_amount) VALUES ('1','100.00');
    INSERT INTO sales (customer_id, sales_amount) VALUES ('2','45.00');
    INSERT INTO sales (customer_id, sales_amount) VALUES ('4','15.80');
    

    Denna utdata visas efter att varje post har infogats:

    
    Query OK, 1 row affected (0.01 sec)
    ...
    
  10. Verifiera uppgifterna i sales tabell. Kör denna SELECT kommando:

    SELECT * FROM sales;
    

    Denna lista med försäljningsdata ska nu visas:

    
    +----------+-------------+--------------+
    | order_id | customer_id | sales_amount |
    +----------+-------------+--------------+
    |        1 |           1 |        25.75 |
    |        2 |           2 |        85.25 |
    |        3 |           5 |         3.25 |
    |        4 |           4 |       200.75 |
    |        5 |           5 |        88.10 |
    |        6 |           1 |       100.00 |
    |        7 |           2 |        45.00 |
    |        8 |           4 |        15.80 |
    +----------+-------------+--------------+
    8 rows in set (0.00 sec)
    

Efter att ha ställt in databasen och de relaterade tabellerna kan du nu implementera de olika underfrågorna i MySQL.

Hur man använder en korrelerad underfråga

En korrelerad underfråga är en typ av kapslad fråga som använder värdena från en överordnad fråga. Den här typen av frågor refererar till den överordnade frågan med en kolumn. Den kapslade frågan exekveras en gång för varje rad i den överordnade frågan.

Exemplet nedan visar en fråga som väljer ut alla kunder. Inuti frågan finns en korrelerad underfråga som hämtar det totala försäljningsbeloppet för varje kund från sales bord.

  1. Kör exempelfrågan:

    SELECT
    customer_id,
    customer_name,
    (SELECT SUM(sales_amount)
    FROM sales WHERE customer_id = customers.customer_id) as total_sales_amount
    FROM
    customers;
    

    I det här exemplet är underfrågan SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id , som visas inom parentes.

    En lista över kundernas totala försäljning visas:

    
    +-------------+-----------------+--------------------+
    | customer_id | customer_name   | total_sales_amount |
    +-------------+-----------------+--------------------+
    |           1 | JOHN PAUL       |             125.75 |
    |           2 | PETER DOE       |             130.25 |
    |           3 | MARY DOE        |               NULL |
    |           4 | CHRISTINE JAMES |             216.55 |
    |           5 | MARK WELL       |              91.35 |
    |           6 | FRANK BRIAN     |               NULL |
    +-------------+-----------------+--------------------+
    6 rows in set (0.00 sec)
    

    Utdata ovan från den korrelerade underfrågan kan ge dig en sammanfattad lista över kundernas beställningar. Observera, eftersom customer_id s 3 och 6 har inga associerade poster i försäljningstabellen, deras total_sales_amount är NULL .

  2. Ett mer elegant sätt att presentera den här listan är att returnera 0 istället för NULL för kunder med noll försäljning. För att göra detta, omslut utdata som genereras av underfrågan med en IFNULL(expression, 0) påstående. Kör detta uppdaterade kommando:

     SELECT
     customer_id,
     customer_name,
     IFNULL((SELECT SUM(sales_amount)
     FROM sales WHERE customer_id = customers.customer_id), 0) as total_sales_amount
     FROM
     customers;
    

    Följande utgång visas. MySQL returnerar 0,00 för alla rader som annars skulle ha returnerat NULL värden.

    
    +-------------+-----------------+--------------------+
    | customer_id | customer_name   | total_sales_amount |
    +-------------+-----------------+--------------------+
    |           1 | JOHN PAUL       |             125.75 |
    |           2 | PETER DOE       |             130.25 |
    |           3 | MARY DOE        |               0.00 |
    |           4 | CHRISTINE JAMES |             216.55 |
    |           5 | MARK WELL       |              91.35 |
    |           6 | FRANK BRIAN     |               0.00 |
    +-------------+-----------------+--------------------+
    6 rows in set (0.00 sec)
    

    Detta tillvägagångssätt hjälper till att säkerställa att utdata inte skadar några ytterligare beräkningar på posterna.

Hur man använder en korrelerad delfråga i en jämförelseoperatör

Underfrågor är användbara för att flytta affärslogik till databasfrågenivån. Följande affärsanvändningsfall innehåller korrelerade underfrågor placerade i WHERE-satsen i en överordnad fråga:

  • Tänk på ett scenario där du vill få en lista över alla kunder som är registrerade i databasen och som inte har associerad försäljning. Du kan använda en underfråga tillsammans med MySQL-jämförelseoperatorn NOT IN och hämta dessa kunder:

      SELECT
      customer_id,
      customer_name
      FROM
      customers
      WHERE customer_id NOT IN (SELECT customer_id FROM sales);
    

    I det här exemplet är underfrågan SELECT customer_id FROM sales , som visas inom parentes. SQL-kommandot ovan ger en lista över två kunder som inte finns i försäljningstabellen:

    
    +-------------+---------------+
    | customer_id | customer_name |
    +-------------+---------------+
    |           3 | MARY DOE      |
    |           6 | FRANK BRIAN   |
    +-------------+---------------+
    2 rows in set (0.00 sec)
    

    I en produktionsmiljö kan du använda den här typen av rekord för att fatta bättre affärsbeslut. Du kan till exempel skapa ett skript med ett annat språk som PHP eller Python för att skicka e-post till dessa kunder och fråga om de har problem med att göra en beställning.

  • Ett annat användningsfall är datarensning. Du kan till exempel använda en underfråga för att ta bort kunder som aldrig har lagt en beställning:

      DELETE
      FROM
      customers
      WHERE customer_id NOT IN (SELECT customer_id FROM sales);
    

    SQL-kommandot ovan tar bort de två kunderna och matar ut följande:

    
    Query OK, 2 rows affected (0.01 sec)
    

    Om du kör ett kommando för att lista alla kunder igen, bör dessa kunder inte längre visas i tabellen:

      SELECT *
      FROM
      customers;
    

    Utdata nedan bekräftar att kunder utan tillhörande beställningar raderades:

    
    +-------------+-----------------+
    | customer_id | customer_name   |
    +-------------+-----------------+
    |           1 | JOHN PAUL       |
    |           2 | PETER DOE       |
    |           4 | CHRISTINE JAMES |
    |           5 | MARK WELL       |
    +-------------+-----------------+
    4 rows in set (0.00 sec)
    

Hur man använder en underfråga som en härledd tabell

När underfrågor används i FROM klausul i en överordnad fråga kallas de för härledda tabeller . De är mycket viktiga när du implementerar komplexa frågor som annars skulle kräva en MySQL VIEW , JOIN , eller UNION klausul. En härledd tabell finns i frågan som skapade den och sparas inte permanent i databasen.

När underfrågor används som härledda tabeller, isolerar de de olika delarna av SQL-satsen. Med andra ord ger underfrågan ett förenklat uttryck för en tabell som kan användas inom ramen för den överordnade frågan.

Obs Kom ihåg att varje härledd tabell måste ha alias.

Kör kommandot nedan för att skapa en härledd tabellunderfråga som har alias som order_summary :

SELECT customer_id
FROM
    (
    SELECT
    customer_id,
    count(order_id) as total_orders
    FROM sales
    group by customer_id
    ) as order_summary
WHERE order_summary.total_orders > 1;
Obs

I det här kommandot visas underfrågan inom parentes som:

SELECT
customer_id,
count(order_id) as total_orders
FROM sales
group by customer_id

Ovanstående kommando frågar försäljningstabellen för att fastställa kunder med mer än 1 beställning. När du kör frågan visas denna utdata:


+-------------+
| customer_id |
+-------------+
|           1 |
|           2 |
|           5 |
|           4 |
+-------------+
4 rows in set (0.00 sec)

Listan ovan visar fyra customer_id s som har mer än en beställning. Som ett exempel på affärsanvändning kan du använda en sådan fråga i ett skript som belönar kunder med en bonus vid deras nästa köp.

Mer information

Du kanske vill konsultera följande resurser för ytterligare information om detta ämne. Även om dessa tillhandahålls i hopp om att de kommer att vara användbara, vänligen observera att vi inte kan garantera noggrannheten eller aktualiteten hos externt värdmaterial.

  • MySQL-underfrågor

  1. OPENJSON "Felaktig syntax nära nyckelordet 'med'." i SQL Server (LÖST)

  2. SQL:Välj dynamiskt kolumnnamn baserat på variabel

  3. har många ringt med något som inte är en instans av Sequelize.Model

  4. Hur tar jag reda på vilken transaktion som orsakar en väntar på tabell-metadatalås?