sql >> Database >  >> RDS >> Mysql

Werken met MySQL-subquery's

Een subquery is een SQL-query (Structured Query Language) die is genest in een andere SQL-query. De opdracht waarin de subquery is genest, wordt de bovenliggende query genoemd. Subquery's worden gebruikt om gegevens die in de bovenliggende query worden gebruikt, vooraf te verwerken. Subquery's kunnen worden toegepast in SELECT , INSERT , UPDATE , en DELETE operaties.

Wanneer subquery's worden uitgevoerd, wordt de subquery eerst verwerkt vóór de bovenliggende query. Bij het bouwen van MySQL-applicaties biedt het gebruik van subquery's verschillende voordelen:

  • Ze splitsen de SQL-instructies op in eenvoudige logische eenheden, waardoor ze gemakkelijker te begrijpen en te onderhouden zijn. Met andere woorden, subquery's helpen bij het isoleren van complexe delen van query's.
  • Ze elimineren de noodzaak voor het gebruik van complexeUNION verklaringen enJOIN verklaringen.
  • Ze worden gebruikt om referentiële integriteit af te dwingen in een scenario waarin externe sleutels niet worden geïmplementeerd.
  • Ze helpen ontwikkelaars om bedrijfslogica in de MySQL-query's te coderen.

In deze gids leer je:

  • Een gecorreleerde subquery gebruiken
  • Een gecorreleerde subquery gebruiken in een vergelijkingsoperator
  • Een subquery gebruiken als een afgeleide tabel

Voordat u begint

Zorg ervoor dat u over het volgende beschikt om deze handleiding te volgen:

  1. Als je dit nog niet hebt gedaan, maak dan een Linode-account en Compute Instance aan. Zie onze handleidingen Aan de slag met Linode en Een rekeninstantie maken.

  2. Volg onze handleiding voor het instellen en beveiligen van een rekeninstantie om uw systeem bij te werken. Mogelijk wilt u ook de tijdzone instellen, uw hostnaam configureren, een beperkt gebruikersaccount maken en SSH-toegang versterken.

  3. De MySQL-serversoftware (of MariaDB) die op uw Linode is geïnstalleerd. Raadpleeg de sectie MySQL, die handleidingen bevat die beschrijven hoe MySQL op verschillende Linux-distributies moet worden geïnstalleerd.

De database instellen

Maak eerst een voorbeelddatabase om te begrijpen hoe subquery's werken. Deze voorbeelddatabase wordt gebruikt om de verschillende voorbeeldquery's in deze handleiding uit te voeren:

  1. SSH naar uw server en log in op MySQL als root:

     mysql -u root -p
    

    Voer desgevraagd het root-wachtwoord van uw MySQL-server in en druk op Enter doorgaan. Merk op dat het root-wachtwoord van je MySQL-server niet hetzelfde is als het root-wachtwoord voor je Linode.

    Opmerking

    Als uw wachtwoord niet wordt geaccepteerd, moet u mogelijk de vorige opdracht uitvoeren met sudo :

    sudo mysql -u root -p
    
  2. Als uw wachtwoord is geaccepteerd, zou u de MySQL-prompt moeten zien:

    
    mysql >
    
    Opmerking

    Als u MariaDB gebruikt, ziet u in plaats daarvan mogelijk een prompt zoals de volgende:

    
    MariaDB [(none)]>
    
  3. Een voorbeelddatabase maken met de naam test_db , rennen:

    CREATE DATABASE test_db;
    

    U zou deze uitvoer moeten zien, die bevestigt dat de database met succes is gemaakt:

    
    Query OK, 1 row affected (0.01 sec)
    
  4. Schakel over naar de test_db databank:

    USE test_db;
    

    Je zou deze uitvoer moeten zien:

    
    Database changed
    
  5. Je hebt de test_db . gemaakt en selecteerde het. Maak vervolgens een tabel met de naam customers :

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

    Je zou deze uitvoer moeten zien:

    
    Query OK, 0 rows affected (0.03 sec)
    
  6. Voeg enkele records toe aan de customers tafel. Voer de onderstaande INSERT . uit commando's een voor een:

    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');
    

    Deze uitvoer wordt weergegeven nadat elke record is ingevoegd:

    
    Query OK, 1 row affected (0.00 sec)
    ...
    
  7. Controleer of de informatie van de klant in de database is ingevoerd. Voer deze SELECT uit commando:

    SELECT * FROM customers;
    

    U zou deze lijst met klanten moeten zien:

    
    +-------------+-----------------+
    | 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. Maak een sales tafel. Deze tabel gebruikt de kolom customer_id om te verwijzen naar de customers tafel:

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

    Deze uitvoer verschijnt:

    
    Query OK, 0 rows affected (0.03 sec)
    
  9. Vul vervolgens de sales tabel met enkele records. Voer de onderstaande INSERT . uit commando's een voor een:

    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');
    

    Deze uitvoer wordt weergegeven nadat elke record is ingevoegd:

    
    Query OK, 1 row affected (0.01 sec)
    ...
    
  10. Controleer de gegevens in de sales tafel. Voer deze SELECT uit commando:

    SELECT * FROM sales;
    

    Deze lijst met verkoopgegevens zou nu moeten worden weergegeven:

    
    +----------+-------------+--------------+
    | 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)
    

Na het instellen van de database en de gerelateerde tabellen, kunt u nu de verschillende subquery's in MySQL implementeren.

Een gecorreleerde subquery gebruiken

Een gecorreleerde subquery is een type geneste query die de waarden van een bovenliggende query gebruikt. Dit soort query's verwijzen naar de bovenliggende query met een kolom. De geneste query wordt één keer uitgevoerd voor elke rij in de bovenliggende query.

In het onderstaande voorbeeld wordt een query weergegeven die alle klanten selecteert. Binnen de zoekopdracht is er een gecorreleerde subquery die het totale verkoopbedrag voor elke klant ophaalt uit de sales tafel.

  1. Voer de voorbeeldquery uit:

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

    In dit voorbeeld is de subquery SELECT SUM(sales_amount) FROM sales WHERE customer_id = customers.customer_id , die tussen haakjes verschijnt.

    Er verschijnt een lijst met de totale verkopen van klanten:

    
    +-------------+-----------------+--------------------+
    | 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)
    

    De bovenstaande uitvoer van de gecorreleerde subquery kan u een samengevatte lijst geven van de bestellingen van de klanten. Let op, aangezien customer_id s 3 en 6 geen gekoppelde records in de verkooptabel hebben, hun total_sales_amount is NULL .

  2. Een elegantere manier om deze lijst weer te geven, is door 0 te retourneren in plaats van NULL voor de klanten zonder verkoop. Om dit te doen, moet u de uitvoer die door de subquery is gegenereerd, omsluiten met een IFNULL(expression, 0) uitspraak. Voer deze bijgewerkte opdracht uit:

     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;
    

    De volgende uitvoer verschijnt. MySQL retourneert 0.00 voor alle rijen die anders NULL zouden hebben geretourneerd waarden.

    
    +-------------+-----------------+--------------------+
    | 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)
    

    Deze aanpak helpt ervoor te zorgen dat de uitvoer geen verdere berekeningen op de records schaadt.

Een gecorreleerde subquery gebruiken in een vergelijkingsoperator

Subquery's zijn handig om bedrijfslogica naar het databasequeryniveau te verplaatsen. De volgende zakelijke use-cases bevatten gecorreleerde subquery's die in de WHERE-component van een bovenliggende query zijn geplaatst:

  • Overweeg een scenario waarin u een lijst wilt krijgen van alle klanten die in de database zijn geregistreerd en waaraan geen verkopen zijn gekoppeld. U kunt een subquery gebruiken samen met de MySQL-vergelijkingsoperator NOT IN en haal deze klanten op:

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

    In dit voorbeeld is de subquery SELECT customer_id FROM sales , die tussen haakjes wordt weergegeven. Het bovenstaande SQL-commando geeft een lijst met twee klanten die niet in de verkooptabel staan:

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

    In een productieomgeving kunt u dit soort records gebruiken om betere zakelijke beslissingen te nemen. U kunt bijvoorbeeld een script maken met een andere taal zoals PHP of Python om deze klanten te e-mailen en te informeren of ze een probleem hebben met het plaatsen van een bestelling.

  • Een andere use-case is het opschonen van gegevens. U kunt bijvoorbeeld een subquery gebruiken om klanten te verwijderen die nog nooit een bestelling hebben geplaatst:

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

    Het bovenstaande SQL-commando verwijdert de twee klanten en geeft het volgende weer:

    
    Query OK, 2 rows affected (0.01 sec)
    

    Als u een opdracht uitvoert om alle klanten opnieuw op te sommen, zouden deze klanten niet langer in de tabel moeten verschijnen:

      SELECT *
      FROM
      customers;
    

    De onderstaande output bevestigt dat de klanten zonder bijbehorende bestellingen zijn verwijderd:

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

Een subquery gebruiken als een afgeleide tabel

Wanneer subquery's worden gebruikt in de FROM clausule van een bovenliggende zoekopdracht, worden ze afgeleide tabellen genoemd . Ze zijn erg belangrijk bij het implementeren van complexe zoekopdrachten waarvoor anders een MySQL VIEW nodig zou zijn , JOIN , of UNION clausule. Er bestaat een afgeleide tabel in de query die deze heeft gemaakt en wordt niet permanent in de database opgeslagen.

Wanneer subquery's worden gebruikt als afgeleide tabellen, isoleren ze de verschillende delen van de SQL-instructie. Met andere woorden, de subquery biedt een vereenvoudigde uitdrukking van een tabel die kan worden gebruikt binnen het bereik van de bovenliggende query.

Opmerking Onthoud dat elke afgeleide tabel een alias moet hebben.

Voer de onderstaande opdracht uit om een ​​afgeleide tabelsubquery te maken met de alias 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;
Opmerking

In deze opdracht verschijnt de subquery tussen haakjes als:

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

De bovenstaande opdracht doorzoekt de verkooptabel om klanten met meer dan 1 bestelling te bepalen. Wanneer u de query uitvoert, verschijnt deze uitvoer:


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

De bovenstaande lijst toont vier customer_id s die meer dan één bestelling hebben. Als voorbeeld van een zakelijke use-case kunt u een dergelijke zoekopdracht gebruiken in een script dat klanten beloont met een bonus bij hun volgende aankoop.

Meer informatie

U kunt de volgende bronnen raadplegen voor aanvullende informatie over dit onderwerp. Hoewel deze worden verstrekt in de hoop dat ze nuttig zullen zijn, houd er rekening mee dat we niet kunnen instaan ​​voor de nauwkeurigheid of tijdigheid van extern gehost materiaal.

  • MySQL-subquery's

  1. Dapper gebruiken met Oracle-opgeslagen procedures die cursors retourneren

  2. Dia's en voorbeelden van SQL-intersecties

  3. SQLite JSON_REPLACE()

  4. Hoe array of meerdere waarden in één kolom op te slaan