Apa kegunaan untuk Cross Join?

105

Gabungan silang melakukan produk kartesius pada tupel dari dua set.

SELECT *
FROM Table1
CROSS JOIN Table2

Keadaan apa yang membuat operasi SQL seperti itu sangat berguna?

Llyle
sumber
36
Sangat menyedihkan bahwa pertanyaan ini telah ditutup. Saya pikir itu bisa ditandai sebagai Wiki Komunitas, tetapi mengatakan itu tidak membangun adalah tidak adil.
Wayne Koorts
1
Saya setuju. Ini menjawab pertanyaan yang saya miliki.
Hades
10
Ada kalanya pengembang yang lebih baru kesulitan memahami implikasi fungsi tertentu dari perangkat lunak yang mereka gunakan. Pertanyaan seperti ini sangat membantu bagi developer yang lebih baru, terutama karena diskusi berikut menjelaskan banyak kemungkinan yang tidak pernah dipertimbangkan oleh developer junior. Format pertanyaannya paling dasar, tetapi maksudnya tampaknya jujur ​​karena bertanya "mengapa ini ada?" Saya setuju dengan Wayne Koorts, sayang sekali casperOne memilih untuk menutup ini dan menyebutnya "tidak konstruktif". Bagian "tidak membangun" membuat saya kesal.
Kaorie

Jawaban:

93

Jika Anda memiliki "kisi" yang ingin Anda isi seluruhnya, seperti informasi ukuran dan warna untuk artikel pakaian tertentu:

select 
    size,
    color
from
    sizes CROSS JOIN colors

Mungkin Anda menginginkan tabel yang berisi baris untuk setiap menit dalam sehari, dan Anda ingin menggunakannya untuk memverifikasi bahwa prosedur telah dijalankan setiap menit, jadi Anda mungkin melintasi tiga tabel:

select
    hour,
    minute
from
    hours CROSS JOIN minutes

Atau Anda memiliki sekumpulan spesifikasi laporan standar yang ingin Anda terapkan setiap bulan dalam setahun:

select
    specId,
    month
from
    reports CROSS JOIN months

Masalah dengan mempertahankan ini sebagai pandangan adalah bahwa dalam banyak kasus, Anda tidak menginginkan produk yang lengkap, terutama yang berkaitan dengan pakaian. Anda dapat menambahkan MINUSlogika ke kueri untuk menghapus kombinasi tertentu yang tidak Anda bawa, tetapi Anda mungkin merasa lebih mudah untuk mengisi tabel dengan cara lain dan tidak menggunakan produk Cartesian.

Selain itu, Anda mungkin akan mencoba gabungan silang pada tabel yang mungkin memiliki beberapa baris lebih banyak dari yang Anda kira, atau mungkin WHEREklausa Anda sebagian atau seluruhnya hilang. Dalam hal ini, DBA Anda akan segera memberi tahu Anda tentang kelalaian tersebut. Biasanya dia tidak akan bahagia.

Dave DuPlantis
sumber
5
... Dalam hal ini, DBA Anda akan segera memberi tahu Anda tentang kelalaian tersebut. Biasanya dia tidak akan bahagia. ... haha, benar sekali!
RSW
2
@ Dave: Bukankah contoh kedua akan menjadi hanya jam CROSS JOIN menit?
Rakesh
@Rakesh, tangkapan bagus, saya sedang memikirkan sesuatu selain apa yang saya ketik. Tetap.
Dave DuPlantis
1
Saya dapat membayangkan cross join menjadi sangat praktis jika Anda diberi 2 set id (mungkin dalam format csv), satu set akan berisi id karyawan dan yang lainnya akan berisi id tugas. Idenya adalah Anda memiliki tabel M2M untuk EmployeeTask. Anda dapat menggunakan gabungan silang untuk menetapkan setiap tugas yang diberikan kepada setiap karyawan tertentu, asalkan Anda mengubah csv menjadi variabel tabel (atau sesuatu).
SynBiotik
20

Hasilkan data untuk pengujian.

Ovidiu Pacurar
sumber
Saya tidak pernah berpikir saya akan melihat "jawaban" 4 kata menerima 9 suara positif.
mickmackusa
14

Anda biasanya tidak menginginkan produk Cartesian lengkap untuk sebagian besar kueri database. Seluruh kekuatan database relasional adalah Anda dapat menerapkan batasan apa pun yang mungkin Anda minati untuk memungkinkan Anda menghindari penarikan baris yang tidak perlu dari db.

Saya kira satu contoh buatan yang mungkin Anda inginkan adalah jika Anda memiliki tabel karyawan dan tabel pekerjaan yang perlu dilakukan dan ingin melihat semua kemungkinan penugasan dari satu karyawan untuk satu pekerjaan.

Randy
sumber
11

Oke, ini mungkin tidak akan menjawab pertanyaannya, tetapi, jika itu benar (dan saya bahkan tidak yakin tentang itu) itu sedikit sejarah yang menyenangkan.

Pada masa-masa awal Oracle, salah satu pengembang menyadari bahwa dia perlu menduplikasi setiap baris dalam sebuah tabel (misalnya, mungkin saja itu adalah tabel kejadian dan dia perlu mengubahnya secara terpisah "mulai acara" dan "acara akhir" entri). Dia menyadari bahwa jika dia memiliki tabel dengan hanya dua baris, dia dapat melakukan penggabungan silang, hanya memilih kolom di tabel pertama, dan mendapatkan apa yang dia butuhkan. Jadi dia membuat meja sederhana, yang secara alami dia sebut "DUAL".

Nanti, dia perlu melakukan sesuatu yang hanya bisa dilakukan melalui pemilihan dari tabel, meskipun aksinya sendiri tidak ada hubungannya dengan tabel, (mungkin dia lupa jam tangannya dan ingin membaca waktu melalui SELECT SYSDATE FROM .. .) Dia menyadari bahwa dia masih memiliki meja DUAL tergeletak di sekitar, dan menggunakannya. Setelah beberapa saat, dia lelah melihat waktu dicetak dua kali, jadi dia akhirnya menghapus salah satu baris.

Orang lain di Oracle mulai menggunakan mejanya, dan akhirnya, diputuskan untuk memasukkannya ke dalam instalasi Oracle standar.

Yang menjelaskan mengapa tabel yang hanya memiliki satu baris memiliki nama yang berarti "dua".

James Curran
sumber
8

Kuncinya adalah "tunjukkan semua kemungkinan kombinasi". Saya telah menggunakan ini bersama dengan kolom kalkulasi lain dan kemudian mengurutkan / memfilternya.

Misalnya, Anda sedang membangun aplikasi arbitrase (perdagangan). Anda memiliki penjual yang menawarkan produk dengan harga tertentu dan pembeli meminta produk dengan harga tertentu. Anda melakukan cross join pada product key (untuk mencocokkan calon pembeli dan penjual), menghitung spread antara cost dan price, lalu mengurutkan desc. dalam hal ini untuk memberi Anda (perantara) perdagangan paling menguntungkan untuk dieksekusi. Hampir selalu Anda akan memiliki kriteria filter pembatas lainnya tentunya.

Kevin Dostalek
sumber
Ah! Penjelasan ini paling masuk akal bagi saya. Dalam hal ini, INNER JOIN tidak masuk akal karena tidak ada hubungan antara ID produk dan penjual, karena beberapa penjual dapat menjual produk yang sama.
moonman239
3

Mengambil sesuatu seperti tabel digit, yang memiliki sepuluh baris untuk digit 0-9. Anda dapat menggunakan gabungan silang pada tabel itu beberapa kali untuk mendapatkan hasil yang memiliki berapa banyak baris yang Anda butuhkan, dengan hasil yang dinomori dengan tepat. Ini memiliki sejumlah kegunaan. Misalnya, Anda bisa menggabungkannya dengan fungsi datadd () untuk mendapatkan satu set untuk setiap hari di tahun tertentu.

Joel Coehoorn
sumber
2

Ini adalah cara yang menarik untuk menggunakan gabungan silang untuk membuat laporan tab silang . Saya menemukannya di SQL For Smarties Joe Celko , dan telah menggunakannya beberapa kali. Memang membutuhkan sedikit pengaturan, tetapi waktu yang telah diinvestasikan sepadan.

Jeff Jones
sumber
1

Bayangkan Anda memiliki serangkaian pertanyaan yang ingin Anda keluarkan atas kombinasi item dan tanggal tertentu (harga, ketersediaan, dll ..). Anda dapat memuat item dan tanggal ke tabel temp yang terpisah dan membuat kueri Anda bergabung dengan tabel. Ini mungkin lebih mudah daripada alternatif untuk menghitung item dan tanggal dalam klausa IN, terutama karena beberapa database membatasi jumlah elemen dalam klausa IN.

sepenuhnya
sumber
1

Anda dapat menggunakannya CROSS JOIN untuk: - menghasilkan data untuk tujuan pengujian - menggabungkan semua properti - Anda memerlukan semua kemungkinan kombinasi misalnya golongan darah (A, B, ..) dengan Rh - / +, dll ... - menyetelnya untuk tujuan Anda;) - Saya tidak ahli di bidang ini;)

CREATE TABLE "HR"."BL_GRP_01" 
("GR_1" VARCHAR2(5 BYTE));
REM INSERTING into BL_GRP_01
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_01 (GR_1) values (NULL);

CREATE TABLE "HR"."BL_GRP_02" 
("GR_1" VARCHAR2(5 BYTE));

REM INSERTING into BL_GRP_02
SET DEFINE OFF;
Insert into BL_GRP_02 (GR_1) values ('A');
Insert into BL_GRP_02 (GR_1) values ('B');
Insert into BL_GRP_02 (GR_1) values ('O');
Insert into BL_GRP_02 (GR_1) values (NULL);

CREATE TABLE "HR"."RH_VAL_01" 
("RH_VAL" VARCHAR2(5 BYTE));
REM INSERTING into RH_VAL_01
SET DEFINE OFF;
Insert into RH_VAL_01 (RH_VAL) values ('+');
Insert into RH_VAL_01 (RH_VAL) values ('-');
Insert into RH_VAL_01 (RH_VAL) values (NULL);

select distinct  a.GR_1 || b.GR_1 || c.RH_VAL as BL_GRP
from BL_GRP_01 a, BL_GRP_02 b, RH_VAL_01 c
GROUP BY a.GR_1, b.GR_1, c.RH_VAL;
  • buat gabungan untuk 2 tabel tanpa id umum dan kemudian kelompokkan menggunakan max (), dll .. untuk menemukan kombinasi setinggi mungkin
HankerPL
sumber