Mysql
 sql >> Teknologi Basis Data >  >> RDS >> Mysql

Kueri SQL mengembalikan data dari beberapa tabel

Bagian 1 - Bergabung dan Bersatu

Jawaban ini mencakup:

  1. Bagian 1
    • Menggabungkan dua tabel atau lebih menggunakan gabungan dalam (Lihat entri wikipedia untuk info tambahan)
    • Cara menggunakan kueri gabungan
    • Gabungan Luar Kiri dan Kanan (ini jawaban stackOverflow sangat bagus untuk mendeskripsikan jenis gabungan)
    • Perpotongan kueri (dan cara mereproduksinya jika database Anda tidak mendukungnya) - ini adalah fungsi dari SQL-Server (lihat info ) dan bagian dari alasan saya menulis semua ini di tempat pertama.
  2. Bagian 2
    • Subkueri - apa itu, di mana bisa digunakan, dan apa yang harus diperhatikan
    • Cartesian bergabung dengan AKA - Oh, kesengsaraan!

Ada beberapa cara untuk mengambil data dari beberapa tabel dalam database. Dalam jawaban ini, saya akan menggunakan sintaks gabungan ANSI-92. Ini mungkin berbeda dengan sejumlah tutorial lain di luar sana yang menggunakan sintaks ANSI-89 yang lebih lama (dan jika Anda terbiasa dengan 89, mungkin tampak kurang intuitif - tetapi yang bisa saya katakan hanyalah mencobanya) seperti apa adanya banyak lebih mudah dipahami ketika kueri mulai menjadi lebih kompleks. Mengapa menggunakannya? Apakah ada peningkatan kinerja? jawaban singkat tidak, tapi adalah lebih mudah dibaca setelah Anda terbiasa. Lebih mudah untuk membaca kueri yang ditulis oleh orang lain menggunakan sintaks ini.

Saya juga akan menggunakan konsep caryard kecil yang memiliki database untuk melacak mobil apa saja yang tersedia. Pemilik telah mempekerjakan Anda sebagai orang IT Computer-nya dan mengharapkan Anda dapat memberikan data yang dia minta dengan mudah.

Saya telah membuat beberapa tabel pencarian yang akan digunakan oleh tabel akhir. Ini akan memberi kita model yang masuk akal untuk bekerja. Untuk memulai, saya akan menjalankan kueri saya terhadap contoh database yang memiliki struktur berikut. Saya akan mencoba memikirkan kesalahan umum yang dibuat saat memulai dan menjelaskan apa yang salah dengannya - serta tentu saja menunjukkan cara memperbaikinya.

Tabel pertama hanyalah daftar warna sehingga kita tahu warna apa yang kita miliki di halaman mobil.

mysql> create table colors(id int(3) not null auto_increment primary key, 
    -> color varchar(15), paint varchar(10));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from colors;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(3)      | NO   | PRI | NULL    | auto_increment |
| color | varchar(15) | YES  |     | NULL    |                |
| paint | varchar(10) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
3 rows in set (0.01 sec)

mysql> insert into colors (color, paint) values ('Red', 'Metallic'), 
    -> ('Green', 'Gloss'), ('Blue', 'Metallic'), 
    -> ('White' 'Gloss'), ('Black' 'Gloss');
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from colors;
+----+-------+----------+
| id | color | paint    |
+----+-------+----------+
|  1 | Red   | Metallic |
|  2 | Green | Gloss    |
|  3 | Blue  | Metallic |
|  4 | White | Gloss    |
|  5 | Black | Gloss    |
+----+-------+----------+
5 rows in set (0.00 sec)

Tabel merek mengidentifikasi berbagai merek mobil di luar caryard yang mungkin bisa dijual.

mysql> create table brands (id int(3) not null auto_increment primary key, 
    -> brand varchar(15));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from brands;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(3)      | NO   | PRI | NULL    | auto_increment |
| brand | varchar(15) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.01 sec)

mysql> insert into brands (brand) values ('Ford'), ('Toyota'), 
    -> ('Nissan'), ('Smart'), ('BMW');
Query OK, 5 rows affected (0.00 sec)
Records: 5  Duplicates: 0  Warnings: 0

mysql> select * from brands;
+----+--------+
| id | brand  |
+----+--------+
|  1 | Ford   |
|  2 | Toyota |
|  3 | Nissan |
|  4 | Smart  |
|  5 | BMW    |
+----+--------+
5 rows in set (0.00 sec)

Tabel model akan mencakup berbagai jenis mobil, akan lebih mudah untuk menggunakan jenis mobil yang berbeda daripada model mobil yang sebenarnya.

mysql> create table models (id int(3) not null auto_increment primary key, 
    -> model varchar(15));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from models;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(3)      | NO   | PRI | NULL    | auto_increment |
| model | varchar(15) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+
2 rows in set (0.00 sec)

mysql> insert into models (model) values ('Sports'), ('Sedan'), ('4WD'), ('Luxury');
Query OK, 4 rows affected (0.00 sec)
Records: 4  Duplicates: 0  Warnings: 0

mysql> select * from models;
+----+--------+
| id | model  |
+----+--------+
|  1 | Sports |
|  2 | Sedan  |
|  3 | 4WD    |
|  4 | Luxury |
+----+--------+
4 rows in set (0.00 sec)

Dan akhirnya, untuk mengikat semua meja lainnya, meja yang mengikat semuanya menjadi satu. Bidang ID sebenarnya adalah nomor lot unik yang digunakan untuk mengidentifikasi mobil.

mysql> create table cars (id int(3) not null auto_increment primary key, 
    -> color int(3), brand int(3), model int(3));
Query OK, 0 rows affected (0.01 sec)

mysql> show columns from cars;
+-------+--------+------+-----+---------+----------------+
| Field | Type   | Null | Key | Default | Extra          |
+-------+--------+------+-----+---------+----------------+
| id    | int(3) | NO   | PRI | NULL    | auto_increment |
| color | int(3) | YES  |     | NULL    |                |
| brand | int(3) | YES  |     | NULL    |                |
| model | int(3) | YES  |     | NULL    |                |
+-------+--------+------+-----+---------+----------------+
4 rows in set (0.00 sec)

mysql> insert into cars (color, brand, model) values (1,2,1), (3,1,2), (5,3,1), 
    -> (4,4,2), (2,2,3), (3,5,4), (4,1,3), (2,2,1), (5,2,3), (4,5,1);
Query OK, 10 rows affected (0.00 sec)
Records: 10  Duplicates: 0  Warnings: 0

mysql> select * from cars;
+----+-------+-------+-------+
| id | color | brand | model |
+----+-------+-------+-------+
|  1 |     1 |     2 |     1 |
|  2 |     3 |     1 |     2 |
|  3 |     5 |     3 |     1 |
|  4 |     4 |     4 |     2 |
|  5 |     2 |     2 |     3 |
|  6 |     3 |     5 |     4 |
|  7 |     4 |     1 |     3 |
|  8 |     2 |     2 |     1 |
|  9 |     5 |     2 |     3 |
| 10 |     4 |     5 |     1 |
+----+-------+-------+-------+
10 rows in set (0.00 sec)

Ini akan memberi kita cukup data (saya harap) untuk menutupi contoh di bawah ini dari berbagai jenis gabungan dan juga memberikan data yang cukup untuk membuatnya bermanfaat.

Jadi intinya, bos ingin tahu ID semua mobil sport yang dia miliki .

Ini adalah gabungan dua tabel sederhana. Kami memiliki tabel yang mengidentifikasi model dan tabel dengan stok yang tersedia di dalamnya. Seperti yang Anda lihat, data dalam models kolom cars tabel berhubungan dengan models kolom cars meja yang kita miliki. Sekarang, kita tahu bahwa tabel model memiliki ID 1 untuk Sports jadi mari kita tulis bergabung.

select
    ID,
    model
from
    cars
        join models
            on model=ID

Jadi kueri ini terlihat bagus bukan? Kami telah mengidentifikasi dua tabel dan berisi informasi yang kami butuhkan dan menggunakan gabungan yang mengidentifikasi dengan benar kolom mana yang akan digabungkan.

ERROR 1052 (23000): Column 'ID' in field list is ambiguous

Oh tidak! Kesalahan dalam kueri pertama kami! Ya, dan itu adalah buah prem. Anda lihat, kueri memang mendapatkan kolom yang tepat, tetapi beberapa di antaranya ada di kedua tabel, sehingga database menjadi bingung tentang kolom apa yang sebenarnya kami maksud dan di mana. Ada dua solusi untuk mengatasi ini. Yang pertama bagus dan sederhana, kita bisa menggunakan tableName.columnName untuk memberi tahu database apa yang kami maksud, seperti ini:

select
    cars.ID,
    models.model
from
    cars
        join models
            on cars.model=models.ID

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  3 | Sports |
|  8 | Sports |
| 10 | Sports |
|  2 | Sedan  |
|  4 | Sedan  |
|  5 | 4WD    |
|  7 | 4WD    |
|  9 | 4WD    |
|  6 | Luxury |
+----+--------+
10 rows in set (0.00 sec)

Yang lain mungkin lebih sering digunakan dan disebut table aliasing. Tabel dalam contoh ini memiliki nama sederhana yang bagus dan pendek, tetapi mengetikkan sesuatu seperti KPI_DAILY_SALES_BY_DEPARTMENT mungkin akan cepat tua, jadi cara sederhananya adalah dengan memberi nama tabel seperti ini:

select
    a.ID,
    b.model
from
    cars a
        join models b
            on a.model=b.ID

Sekarang, kembali ke permintaan. Seperti yang Anda lihat, kami memiliki informasi yang kami butuhkan, tetapi kami juga memiliki informasi yang tidak diminta, jadi kami perlu menyertakan klausa where dalam pernyataan untuk hanya mendapatkan mobil sport seperti yang diminta. Karena saya lebih suka metode alias tabel daripada menggunakan nama tabel berulang-ulang, saya akan tetap menggunakannya mulai saat ini.

Jelas, kita perlu menambahkan klausa where ke kueri kita. Kami dapat mengidentifikasi mobil Sport baik dengan ID=1 atau model='Sports' . Karena ID diindeks dan kunci utama (dan kebetulan lebih sedikit mengetik), mari gunakan itu dalam kueri kita.

select
    a.ID,
    b.model
from
    cars a
        join models b
            on a.model=b.ID
where
    b.ID=1

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  3 | Sports |
|  8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)

Bingo! Bos senang. Tentu saja, sebagai bos dan tidak pernah puas dengan apa yang dia minta, dia melihat informasinya, lalu berkata Aku juga mau warnanya .

Oke, jadi kami memiliki bagian yang baik dari kueri kami yang sudah ditulis, tetapi kami perlu menggunakan tabel ketiga yaitu warna. Sekarang, tabel informasi utama kami cars menyimpan ID warna mobil dan tautan ini kembali ke kolom ID warna. Jadi, dengan cara yang mirip dengan aslinya, kita dapat menggabungkan tabel ketiga:

select
    a.ID,
    b.model
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
where
    b.ID=1

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  3 | Sports |
|  8 | Sports |
| 10 | Sports |
+----+--------+
4 rows in set (0.00 sec)

Sial, meskipun tabel digabungkan dengan benar dan kolom terkait ditautkan, kami lupa memasukkan informasi yang sebenarnya dari tabel baru yang baru saja kita tautkan.

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
where
    b.ID=1

+----+--------+-------+
| ID | model  | color |
+----+--------+-------+
|  1 | Sports | Red   |
|  8 | Sports | Green |
| 10 | Sports | White |
|  3 | Sports | Black |
+----+--------+-------+
4 rows in set (0.00 sec)

Benar, itu bos kami sejenak. Sekarang, untuk menjelaskan beberapa hal ini secara lebih rinci. Seperti yang Anda lihat, from klausa dalam pernyataan kami menautkan tabel utama kami (Saya sering menggunakan tabel yang berisi informasi daripada tabel pencarian atau dimensi. Kueri akan bekerja dengan baik dengan semua tabel yang dialihkan, tetapi kurang masuk akal ketika kami kembali ke kueri ini untuk membacanya dalam waktu beberapa bulan, jadi seringkali yang terbaik adalah mencoba menulis kueri yang bagus dan mudah dimengerti - susunlah secara intuitif, gunakan indentasi yang bagus sehingga semuanya sejelas mungkin. Jika Anda lanjutkan untuk mengajar orang lain, cobalah untuk menanamkan karakteristik ini dalam pertanyaan mereka - terutama jika Anda akan memecahkan masalah mereka.

Sangat mungkin untuk terus menautkan lebih banyak tabel dengan cara ini.

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1

Sementara saya lupa menyertakan tabel di mana kita mungkin ingin menggabungkan lebih dari satu kolom di join pernyataan, berikut adalah contohnya. Jika models tabel memiliki model khusus merek dan oleh karena itu juga memiliki kolom yang disebut brand yang ditautkan kembali ke brands tabel pada ID lapangan, itu bisa dilakukan seperti ini:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
            and b.brand=d.ID
where
    b.ID=1

Anda bisa lihat, kueri di atas tidak hanya menghubungkan tabel yang digabungkan ke cars utama tabel, tetapi juga menentukan gabungan antara tabel yang sudah bergabung. Jika ini tidak dilakukan, hasilnya disebut cartesian join - yang merupakan dba speak for bad. Gabungan kartesius adalah gabungan di mana baris dikembalikan karena informasinya tidak memberi tahu database cara membatasi hasil, jadi kueri mengembalikan semua baris yang sesuai dengan kriteria.

Jadi, untuk memberikan contoh gabungan kartesius, mari jalankan kueri berikut:

select
    a.ID,
    b.model
from
    cars a
        join models b

+----+--------+
| ID | model  |
+----+--------+
|  1 | Sports |
|  1 | Sedan  |
|  1 | 4WD    |
|  1 | Luxury |
|  2 | Sports |
|  2 | Sedan  |
|  2 | 4WD    |
|  2 | Luxury |
|  3 | Sports |
|  3 | Sedan  |
|  3 | 4WD    |
|  3 | Luxury |
|  4 | Sports |
|  4 | Sedan  |
|  4 | 4WD    |
|  4 | Luxury |
|  5 | Sports |
|  5 | Sedan  |
|  5 | 4WD    |
|  5 | Luxury |
|  6 | Sports |
|  6 | Sedan  |
|  6 | 4WD    |
|  6 | Luxury |
|  7 | Sports |
|  7 | Sedan  |
|  7 | 4WD    |
|  7 | Luxury |
|  8 | Sports |
|  8 | Sedan  |
|  8 | 4WD    |
|  8 | Luxury |
|  9 | Sports |
|  9 | Sedan  |
|  9 | 4WD    |
|  9 | Luxury |
| 10 | Sports |
| 10 | Sedan  |
| 10 | 4WD    |
| 10 | Luxury |
+----+--------+
40 rows in set (0.00 sec)

Ya Tuhan, itu jelek. Namun, sejauh menyangkut database, ini tepat apa yang diminta. Dalam kueri, kami meminta ID dari cars dan models dari models . Namun, karena kami tidak menentukan bagaimana untuk bergabung dengan tabel, database telah cocok dengan setiap baris dari tabel pertama dengan setiap baris dari tabel kedua.

Oke, jadi bos sudah kembali, dan dia ingin informasi lebih lanjut lagi. Saya ingin daftar yang sama, tetapi juga menyertakan 4WD di dalamnya .

Namun, ini memberi kita alasan yang bagus untuk melihat dua cara berbeda untuk mencapai ini. Kita bisa menambahkan kondisi lain ke klausa where seperti ini:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1
    or b.ID=3

Meskipun hal di atas akan bekerja dengan sangat baik, mari kita lihat secara berbeda, ini adalah alasan yang bagus untuk menunjukkan bagaimana union kueri akan berfungsi.

Kami tahu bahwa berikut ini akan mengembalikan semua mobil Sport:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1

Dan berikut ini akan mengembalikan semua 4WD:

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=3

Jadi dengan menambahkan union all klausa di antara mereka, hasil kueri kedua akan ditambahkan ke hasil kueri pertama.

select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=1
union all
select
    a.ID,
    b.model,
    c.color
from
    cars a
        join models b
            on a.model=b.ID
        join colors c
            on a.color=c.ID
        join brands d
            on a.brand=d.ID
where
    b.ID=3

+----+--------+-------+
| ID | model  | color |
+----+--------+-------+
|  1 | Sports | Red   |
|  8 | Sports | Green |
| 10 | Sports | White |
|  3 | Sports | Black |
|  5 | 4WD    | Green |
|  7 | 4WD    | White |
|  9 | 4WD    | Black |
+----+--------+-------+
7 rows in set (0.00 sec)

Seperti yang Anda lihat, hasil kueri pertama dikembalikan terlebih dahulu, diikuti dengan hasil kueri kedua.

Dalam contoh ini, tentu saja akan lebih mudah menggunakan kueri pertama, tetapi union kueri bisa bagus untuk kasus tertentu. Mereka adalah cara yang bagus untuk mengembalikan hasil tertentu dari tabel dari tabel yang tidak mudah digabungkan - atau dalam hal ini sepenuhnya tabel yang tidak berhubungan. Namun ada beberapa aturan yang harus diikuti.

  • Jenis kolom dari kueri pertama harus cocok dengan jenis kolom dari setiap kueri lain di bawah.
  • Nama kolom dari kueri pertama akan digunakan untuk mengidentifikasi seluruh rangkaian hasil.
  • Jumlah kolom dalam setiap kueri harus sama.

Sekarang, Anda mungkin bertanya-tanya apa yang perbedaan antara menggunakan union dan union all . union kueri akan menghapus duplikat, sementara union all tidak akan. Ini berarti ada sedikit peningkatan performa saat menggunakan union lebih dari union all tetapi hasilnya mungkin sepadan - saya tidak akan berspekulasi tentang hal semacam itu dalam hal ini.

Pada catatan ini, mungkin perlu dicatat beberapa catatan tambahan di sini.

  • Jika ingin mengurutkan hasilnya, kita bisa menggunakan order by tetapi Anda tidak dapat menggunakan alias lagi. Dalam kueri di atas, menambahkan order by a.ID akan menghasilkan kesalahan - sejauh menyangkut hasil, kolom tersebut disebut ID daripada a.ID - meskipun alias yang sama telah digunakan di kedua kueri.
  • Kami hanya dapat memiliki satu order by pernyataan, dan harus sebagai pernyataan terakhir.

Untuk contoh berikutnya, saya menambahkan beberapa baris tambahan ke tabel kita.

Saya telah menambahkan Holden ke tabel merek. Saya juga telah menambahkan baris ke cars yang memiliki color nilai 12 - yang tidak memiliki referensi di tabel warna.

Oke, bos kembali lagi, menggonggong permintaan - *Saya ingin menghitung setiap merek yang kami bawa dan jumlah mobil di dalamnya!` - Tipikal, kami hanya sampai pada bagian yang menarik dari diskusi kami dan bos ingin lebih banyak pekerjaan .

Benar, jadi hal pertama yang perlu kita lakukan adalah mendapatkan daftar lengkap kemungkinan merek.

select
    a.brand
from
    brands a

+--------+
| brand  |
+--------+
| Ford   |
| Toyota |
| Nissan |
| Smart  |
| BMW    |
| Holden |
+--------+
6 rows in set (0.00 sec)

Sekarang, ketika kita menggabungkan ini ke tabel mobil kita, kita mendapatkan hasil sebagai berikut:

select
    a.brand
from
    brands a
        join cars b
            on a.ID=b.brand
group by
    a.brand

+--------+
| brand  |
+--------+
| BMW    |
| Ford   |
| Nissan |
| Smart  |
| Toyota |
+--------+
5 rows in set (0.00 sec)

Yang tentu saja menjadi masalah - kami tidak melihat ada penyebutan Holden . yang cantik merek yang saya tambahkan.

Ini karena gabungan mencari baris yang cocok di keduanya tabel. Karena tidak ada data di mobil yang bertipe Holden itu tidak dikembalikan. Di sinilah kita dapat menggunakan outer Ikuti. Ini akan mengembalikan semua hasil dari satu tabel apakah cocok di tabel lain atau tidak:

select
    a.brand
from
    brands a
        left outer join cars b
            on a.ID=b.brand
group by
    a.brand

+--------+
| brand  |
+--------+
| BMW    |
| Ford   |
| Holden |
| Nissan |
| Smart  |
| Toyota |
+--------+
6 rows in set (0.00 sec)

Sekarang setelah kita memilikinya, kita dapat menambahkan fungsi agregat yang indah untuk menghitung dan melepaskan bos sejenak.

select
    a.brand,
    count(b.id) as countOfBrand
from
    brands a
        left outer join cars b
            on a.ID=b.brand
group by
    a.brand

+--------+--------------+
| brand  | countOfBrand |
+--------+--------------+
| BMW    |            2 |
| Ford   |            2 |
| Holden |            0 |
| Nissan |            1 |
| Smart  |            1 |
| Toyota |            5 |
+--------+--------------+
6 rows in set (0.00 sec)

Dan dengan itu, bos bersembunyi.

Sekarang, untuk menjelaskan ini secara lebih rinci, gabungan luar dapat berada di left atau right Tipe. Kiri atau Kanan menentukan tabel mana yang sepenuhnya termasuk. Sebuah left outer join akan menyertakan semua baris dari tabel di sebelah kiri, sementara (Anda dapat menebaknya) right outer join membawa semua hasil dari tabel di sebelah kanan ke hasil.

Beberapa database akan mengizinkan full outer join yang akan mengembalikan hasil (baik cocok atau tidak) dari keduanya tabel, tetapi ini tidak didukung di semua database.

Sekarang, saya mungkin membayangkan pada saat ini, Anda bertanya-tanya apakah Anda dapat menggabungkan tipe gabungan dalam kueri atau tidak - dan jawabannya adalah ya, Anda benar-benar bisa.

select
    b.brand,
    c.color,
    count(a.id) as countOfBrand
from
    cars a
        right outer join brands b
            on b.ID=a.brand
        join colors c
            on a.color=c.ID
group by
    a.brand,
    c.color

+--------+-------+--------------+
| brand  | color | countOfBrand |
+--------+-------+--------------+
| Ford   | Blue  |            1 |
| Ford   | White |            1 |
| Toyota | Black |            1 |
| Toyota | Green |            2 |
| Toyota | Red   |            1 |
| Nissan | Black |            1 |
| Smart  | White |            1 |
| BMW    | Blue  |            1 |
| BMW    | White |            1 |
+--------+-------+--------------+
9 rows in set (0.00 sec)

Lantas, mengapa hasilnya tidak seperti yang diharapkan? Karena meskipun kami telah memilih gabungan luar dari mobil ke merek, itu tidak ditentukan dalam gabungan ke warna - sehingga gabungan tertentu hanya akan mengembalikan hasil yang cocok di kedua tabel.

Berikut adalah kueri yang akan berfungsi untuk mendapatkan hasil yang kami harapkan:

select
    a.brand,
    c.color,
    count(b.id) as countOfBrand
from
    brands a
        left outer join cars b
            on a.ID=b.brand
        left outer join colors c
            on b.color=c.ID
group by
    a.brand,
    c.color

+--------+-------+--------------+
| brand  | color | countOfBrand |
+--------+-------+--------------+
| BMW    | Blue  |            1 |
| BMW    | White |            1 |
| Ford   | Blue  |            1 |
| Ford   | White |            1 |
| Holden | NULL  |            0 |
| Nissan | Black |            1 |
| Smart  | White |            1 |
| Toyota | NULL  |            1 |
| Toyota | Black |            1 |
| Toyota | Green |            2 |
| Toyota | Red   |            1 |
+--------+-------+--------------+
11 rows in set (0.00 sec)

Seperti yang bisa kita lihat, kita memiliki dua gabungan luar dalam kueri dan hasilnya muncul seperti yang diharapkan.

Sekarang, bagaimana dengan jenis gabungan lain yang Anda tanyakan? Bagaimana dengan Persimpangan?

Yah, tidak semua database mendukung intersection tetapi hampir semua database memungkinkan Anda membuat persimpangan melalui gabungan (atau setidaknya pernyataan where yang terstruktur dengan baik).

Persimpangan adalah jenis gabungan yang agak mirip dengan union seperti yang dijelaskan di atas - tetapi perbedaannya adalah hanya mengembalikan baris data yang identik (dan maksud saya identik) antara berbagai kueri individu yang digabungkan oleh gabungan. Hanya baris yang identik dalam segala hal yang akan dikembalikan.

Contoh sederhananya adalah seperti ini:

select
    *
from
    colors
where
    ID>2
intersect
select
    *
from
    colors
where
    id<4

Sementara union normal kueri akan mengembalikan semua baris tabel (kueri pertama mengembalikan apa pun melalui ID>2 dan yang kedua memiliki ID<4 ) yang akan menghasilkan set lengkap, kueri berpotongan hanya akan mengembalikan id=3 yang cocok dengan baris karena memenuhi kedua kriteria.

Sekarang, jika database Anda tidak mendukung intersect query, di atas dapat dengan mudah dicapai dengan query berikut:

select
    a.ID,
    a.color,
    a.paint
from
    colors a
        join colors b
            on a.ID=b.ID
where
    a.ID>2
    and b.ID<4

+----+-------+----------+
| ID | color | paint    |
+----+-------+----------+
|  3 | Blue  | Metallic |
+----+-------+----------+
1 row in set (0.00 sec)

Jika Anda ingin melakukan interseksi di dua tabel berbeda menggunakan database yang tidak mendukung kueri interseksi, Anda harus membuat gabungan di setiap kolom tabel.



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. Di MySQL, dapatkah saya menyalin satu baris untuk dimasukkan ke dalam tabel yang sama?

  2. Sisipkan beberapa baris dengan pernyataan yang disiapkan PDO

  3. Bagaimana mendefinisikan pesanan ORDER BY khusus di mySQL

  4. Peringatan:mysqli_query():Tidak dapat mengambil mysqli

  5. Bagaimana saya bisa mengaktifkan ekstensi MySQLi di PHP 7?