Website-Suche

Kombinieren der Ergebnisse mehrerer SQL-Abfragen mithilfe der UNION-Anweisung


In einem früheren Artikel haben wir über die verschiedenen Arten von JOIN gesprochen, die wir in einer MariaDB/MySQL-Datenbank verwenden können. Dieses Mal werfen wir stattdessen einen Blick auf die UNION-Anweisung: wie sie funktioniert, wie wir sie verwenden können, um das Ergebnis von Abfragen zu kombinieren, die auf verschiedenen Tabellen ausgeführt werden, und was sind ihre Besonderheiten.

In diesem Tutorial lernen Sie:

  • So verwenden Sie die UNION-Anweisung auf einem MariaDB/MySQL-Server
  • Was sind die Eigenschaften der UNION-Anweisung?

Das Ergebnis einer Erklärung der UNION

Verwendete Softwareanforderungen und Konventionen

Die Erklärung der Gewerkschaft

Mit der UNION-Anweisung können wir die Ergebnisse von zwei oder mehr Abfragen kombinieren. Während wir bei der Ausführung eines JOINs eine Aktion ausführen oder zusätzliche Informationen auf der Grundlage bestehender Beziehungen zwischen Tabellen abrufen können, können bei der Verwendung der UNION-Anweisung, wenn einige Bedingungen erfüllt sind, die Zeilen kombiniert werden, die aus Abfragen resultieren, die auf verschiedenen, auch nicht verwandten Tabellen gestartet wurden. In diesem Tutorial sehen wir ein grundlegendes und ein Beispiel aus der Praxis, wie wir die UNION-Anweisung in einer MariaDB/MySQL-Umgebung verwenden können.

Ein einfaches Beispiel

Beginnen wir mit einem sehr einfachen Beispiel, um die Besonderheiten der UNION-Erklärung vorzustellen. Angenommen, wir haben zwei völlig unabhängige Tabellen: die erste heißt "movie" und die zweite "color". In ersterem enthält jede Zeile Informationen über einen Film: den Titel, das Genre und das Veröffentlichungsdatum. Letzteres enthält nur den Namen einiger Farben. So sehen die Tabellen aus:

+----+---------------+---------+--------------+
| id | title         | genre   | release_date |
+----+---------------+---------+--------------+
|  1 | A New Hope    | fantasy | 1977-05-25   |
|  2 | The Godfather | Drama   | 1972-05-24   |
+----+---------------+---------+--------------+

+----+--------+
| id | name   |
+----+--------+
|  1 | blue   |
|  2 | yellow |
+----+--------+

Und das ist ihre Beschreibung:

+--------------+-------------+------+-----+---------+----------------+
| Field        | Type        | Null | Key | Default | Extra          |
+--------------+-------------+------+-----+---------+----------------+
| id           | int(2)      | NO   | PRI | NULL    | auto_increment |
| title        | varchar(20) | NO   |     | NULL    |                |
| genre        | varchar(20) | NO   |     | NULL    |                |
| release_date | date        | NO   |     | NULL    |                |
+--------------+-------------+------+-----+---------+----------------+

+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(2)      | NO   | PRI | NULL    | auto_increment |
| name  | varchar(10) | NO   |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+

Wie bereits erwähnt, haben diese beiden Tabellen absolut keine Verbindung zueinander. Durch die Verwendung der UNION-Anweisung können wir jedoch die Ergebnisse von zwei separaten Abfragen kombinieren, die für sie gestartet wurden. Los geht's:

SELECT title, genre FROM movie UNION SELECT id, name FROM color;

Der obige Befehl gibt folgendes Ergebnis zurück:

+---------------+---------+
| title         | genre   |
+---------------+---------+
| A New Hope    | fantasy |
| The Godfather | Drama   |
| 1             | blue    |
| 2             | yellow  |
+---------------+---------+

Lassen Sie es uns erklären. Wir haben zwei verschiedene SELECT-Abfragen durchgeführt: In der ersten haben wir den Wert der Spalten "title" und "genre" für jede Zeile in der Filmtabelle ausgewählt. In der zweiten haben wir stattdessen die Spalten "id" und "name" aus der Tabelle "color" ausgewählt, wiederum ohne Verwendung eines Filters.

Auch wenn die beiden Tabellen völlig unabhängig voneinander sind, werden die von jeder von ihnen zurückgegebenen Zeilen kombiniert, da wir die UNION-Anweisung zwischen den beiden Abfragen verwendet haben: Das Ergebnis ist die Tabelle, die Sie oben sehen können.

Auch wenn in der überwiegenden Mehrheit der realen Fälle die Spalten, die aus den beteiligten Tabellen ausgewählt wurden, wahrscheinlich die gleichen Datentypen haben würden, können wir in dem dummen Beispiel oben deutlich sehen, wie die UNION auch dann abläuft, wenn die Spalten der beiden ursprünglichen Tabellen unterschiedliche Datentypen enthalten: Beide Spalten, die aus der Tabelle "movie" ausgewählt wurden, sind vom Datentyp VARCHAR, während die Spalte "id" der Tabelle "color" vom Typ INT. Dies ist möglich, da die Datenbank die erforderlichen Datenkonvertierungen automatisch durchführt.

Ein weiterer sehr wichtiger Punkt, den Sie beachten sollten, ist, dass die Spalten im UNION-Ergebnis ihre Namen von denen geerbt haben, die in der ersten Abfrage ausgewählt wurden, der Spalte links neben dem UNION-Schlüsselwort: "title" und "genre". Wenn Sie sich das obige Beispiel ansehen, fragen Sie sich wahrscheinlich, wofür die UNION-Anweisung im realen Leben nützlich sein kann: Sehen wir uns ein anderes Beispiel an.

Der Fantasy-Football-Fall

Vor einiger Zeit war ich an der Erstellung einer kleinen Fantasy-Football-Anwendung beteiligt. In der Datenbank der Anwendung gab es eine Tabelle namens "Club", die Informationen über die am Wettbewerb beteiligten Fantasy-Clubs enthielt. Dies ist ein Auszug daraus:

+----+-----------------+--------+
| id | name            | budget |
+----+-----------------+--------+
|  1 | Havana Blu      |      4 |
|  2 | Longobarda      |      4 |
|  3 | Real Siderno    |      0 |
|  4 | Earthquake Team |     66 |
|  5 | Kalapagos       |     33 |
|  6 | Cantasant       |      5 |
|  7 | F.C. Mojito     |      0 |
|  8 | Apoel Nicotina  |      1 |
|  9 | Dharma          |      0 |
| 10 | Real 1908       |     12 |
+----+-----------------+--------+

Im selben Projekt gab es auch eine Tabelle mit dem Namen "Kalender", in der jede Zeile ein Spiel zwischen zwei der oben aufgeführten Vereine darstellte. Da wir 10 Vereine hatten, fanden an jedem Meisterschaftstag insgesamt 5 Spiele statt. Als Beispiel hier ein Auszug aller Spiele der ersten vier Tage:

+----+-----+------+-------------+-------+--------------+
| id | day | host | host_scores | guest | guest_scores |
+----+-----+------+-------------+-------+--------------+
|  1 |   1 |    2 |        75.5 |     8 |           67 |
|  2 |   1 |    4 |          80 |     6 |           77 |
|  3 |   1 |    7 |          63 |     9 |         71.5 |
|  4 |   1 |    3 |        79.5 |     5 |           68 |
|  5 |   1 |   10 |          64 |     1 |         72.5 |
|  6 |   2 |    5 |        66.5 |    10 |         65.5 |
|  7 |   2 |    9 |          82 |     3 |         62.5 |
|  8 |   2 |    6 |          83 |     7 |         69.5 |
|  9 |   2 |    8 |          77 |     4 |         79.5 |
| 10 |   2 |    1 |          67 |     2 |         81.5 |
| 11 |   3 |    4 |          73 |     2 |           58 |
| 12 |   3 |    7 |        70.5 |     8 |         75.5 |
| 13 |   3 |    3 |        66.5 |     6 |           88 |
| 14 |   3 |   10 |        74.5 |     9 |         60.5 |
| 15 |   3 |    5 |        68.5 |     1 |         72.5 |
| 16 |   4 |    9 |          68 |     5 |           69 |
| 17 |   4 |    6 |          60 |    10 |           66 |
| 18 |   4 |    8 |        70.5 |     3 |         73.5 |
| 19 |   4 |    2 |        71.5 |     7 |           79 |
| 20 |   4 |    1 |        68.5 |     4 |           68 |
+----+-----+------+-------------+-------+--------------+

Die erste Spalte jeder Zeile enthält einen Ersatzschlüssel, der als Primärschlüssel für die Tabelle verwendet wird. Die zweite enthält die ganze Zahl, die den Tag darstellt, an dem das Spiel Teil ist. Die Spalten "Gastgeber", "host_scores" und "Gast" enthalten guest_scores die ID und die Punktzahlen des Clubs, der als Gastgeber gespielt hat, bzw. die des Clubs, der als Gast gespielt hat.

Nehmen wir nun an, wir möchten einen Rang erstellen, in dem alle Vereine in absteigender Reihenfolge auf der Grundlage der Gesamtpunktzahl aufgelistet werden, die sie in den ersten vier Meisterschaftstagen erzielt haben. Wenn jede Club-ID nur in einer Spalte aufgeführt wäre, z. B. "host", wäre die Operation sehr einfach: Wir würden einfach die Summe der Ergebnisse mit der Aggregatfunktion SUM() berechnen und die Ergebnisse nach der ID der Clubs gruppieren und sie in absteigender Reihenfolge anzeigen:

SELECT
    host, SUM(host_scores) AS total_scores
FROM
    calendar
GROUP BY
    host
ORDER BY
    total_scores DESC

Da jedoch an jedem Meisterschaftstag ein Verein abwechselnd als Gastgeber und als Gast spielt, gibt die obige Abfrage nicht die gewünschten Ergebnisse zurück, sondern erzeugt die Gesamtpunktzahl einer Mannschaft, einschließlich der Ergebnisse, die erzielt wurden, wenn sie als Gastgeber (oder alternativ als Gast) gespielt hat.

Das ist ein Fall, in dem sich die UNION-Anweisung als nützlich erweisen kann: Wir können zwei separate Abfragen durchführen, eine mit den Spalten "host" und "host_scores" und die andere mit den Spalten "guest" und "guest_scores"; Wir können dann die UNION-Anweisung verwenden, um die Zeile, die sich aus der zweiten Abfrage ergibt, an die von der ersten zurückgegebenen Zeilen anzuhängen und schließlich die Aggregatwerte zu berechnen. Zusätzlich können wir einen JOIN mit der Tabelle "club" durchführen, um den Namen jedes Clubs im Ergebnis erscheinen zu lassen. Hier ist die vollständige Abfrage:

SELECT
    data.team_id
    , club.name
    , SUM(scores) AS total_scores

FROM  (
    SELECT
        host as team_id
        ,host_scores AS scores
    FROM
        calendar

    UNION ALL

    SELECT
        guest
        ,guest_scores
    FROM
        calendar
) AS data

JOIN club ON club.id = data.team_id
GROUP BY
    data.team_id
ORDER BY
    total_scores DESC;

Hier ist das Ergebnis der Abfrage:

+---------+-----------------+--------------+
| team_id | name            | total_scores |
+---------+-----------------+--------------+
|       6 | Cantasant       |          308 |
|       4 | Earthquake Team |        300.5 |
|       8 | Apoel Nicotina  |          290 |
|       2 | Longobarda      |        286.5 |
|       3 | Real Siderno    |          282 |
|       9 | Dharma          |          282 |
|       7 | F.C. Mojito     |          282 |
|       1 | Havana Blu      |        280.5 |
|       5 | Kalapagos       |          272 |
|      10 | Real 1908       |          270 |
+---------+-----------------+--------------+

Wie Sie sehen können, war am Ende des vierten Meisterschaftstages das Team "Cantasant" das Team mit der höchsten Punktzahl. Eine weitere Sache, die in der obigen Abfrage zu beachten ist, ist die Verwendung des Schlüsselworts ALL zusammen mit UNION: Dies war notwendig, da bei Verwendung der UNION-Anweisung standardmäßig doppelte Zeilen entfernt werden. Wenn stattdessen UNION ALL verwendet wird, werden die Zeilen beibehalten.

Schlüsse

In diesem Tutorial haben wir die UNION-Anweisung in MariaDB/MySQL-Datenbanken kennengelernt. Wir sahen ein einfaches Beispiel, um einige der Eigenschaften der Aussage zu demonstrieren, und ein Beispiel aus der realen Welt, das aus einem realen Projekt entnommen wurde. Zusammenfassend lassen sich die Merkmale einer UNION-Anweisung wie folgt zusammenfassen:

  • In der resultierenden Tabelle werden die Namen der Spalten verwendet, die in der ersten Abfrage ausgewählt wurden.
  • Die Anzahl der Spalten muss in allen Abfragen gleich sein.
  • Die Datentypen der Spalten können unterschiedlich sein, die Datenbank führt die Konvertierung durch.
  • Wenn die UNION-Anweisung verwendet wird, werden standardmäßig doppelte Zeilen in den Ergebnissen entfernt: Um dies zu vermeiden, können wir UNION ALL ;

Erweitern Sie Ihr Wissen über die UNION-Erklärung, indem Sie einen Blick in die offizielle Dokumentation werfen.

Verwandte Artikel: