Jakie są zastosowania funkcji łączenia krzyżowego?


105

Sprzężenie krzyżowe wykonuje iloczyn kartezjański na krotkach dwóch zbiorów.

SELECT *
FROM Table1
CROSS JOIN Table2

W jakich okolicznościach taka operacja SQL jest szczególnie użyteczna?


36
To naprawdę smutne, że to pytanie zostało zamknięte. Myślę, że można by to oznaczyć jako Społeczność Wiki, ale mówienie, że nie jest to konstruktywne, jest niesprawiedliwe.
Wayne Koorts

1
Zgadzam się. To odpowiadało dokładnie na pytanie, które miałem.
Hades

10
Są chwile, kiedy nowszy programista ma problemy ze zrozumieniem konsekwencji niektórych funkcji używanego oprogramowania. Takie pytania są szczególnie pomocne dla nowszych programistów, przede wszystkim dlatego, że dyskusja, która następuje, wyjaśnia wiele możliwości, których młodszy programista nigdy nie rozważał. Forma pytania jest w najlepszym razie elementarna, ale intencja wydaje się być szczera, ponieważ pyta „dlaczego to w ogóle istnieje?” Zgadzam się z Wayne Koortsem, szkoda, że ​​casperOne zdecydował się to zamknąć i nazwał to „nie konstruktywnym”. Szczególnie drażni mnie część „niekonstruktywna”.
Kaorie,

Odpowiedzi:


93

Jeśli masz „siatkę”, którą chcesz wypełnić w całości, np. Informacje o rozmiarze i kolorze określonego elementu odzieży:

select 
    size,
    color
from
    sizes CROSS JOIN colors

Może potrzebujesz tabeli zawierającej wiersz dla każdej minuty w ciągu dnia i chcesz jej użyć do sprawdzenia, czy procedura wykonywała się co minutę, więc możesz skrzyżować trzy tabele:

select
    hour,
    minute
from
    hours CROSS JOIN minutes

Lub masz zestaw standardowych specyfikacji raportów, które chcesz stosować w każdym miesiącu w roku:

select
    specId,
    month
from
    reports CROSS JOIN months

Problem z utrzymaniem ich jako poglądów polega na tym, że w większości przypadków nie chcesz kompletnego produktu, szczególnie w odniesieniu do odzieży. Możesz dodać MINUSlogikę do zapytania, aby usunąć pewne kombinacje, których nie nosisz, ale może być łatwiej wypełnić tabelę w inny sposób i nie używać iloczynu kartezjańskiego.

Możesz również spróbować sprzężenia krzyżowego w tabelach, które mają być może kilka wierszy więcej niż myślisz, lub być może WHEREbrakuje Twojej klauzuli częściowo lub całkowicie. W takim przypadku Twój DBA powiadomi Cię niezwłocznie o zaniedbaniu. Zwykle nie będzie szczęśliwy.


5
... W takim przypadku Twój DBA powiadomi Cię niezwłocznie o zaniedbaniu. Zwykle nie będzie szczęśliwy. ... haha, to prawda!
RSW

2
@Dave: Czy drugi przykład nie będzie tylko godziną CROSS JOIN minut?
Rakesh

@Rakesh, dobry chwyt, myślałem o czymś innym niż to, co piszę. Naprawiony.
Dave DuPlantis

1
Mogę sobie wyobrazić, że łączenie krzyżowe jest bardzo praktyczne, gdybyś otrzymał 2 zestawy identyfikatorów (być może w formacie csv), jeden zestaw zawierałby identyfikatory pracowników, a drugi zawierałby identyfikatory zadań. Chodzi o to, że masz tabelę M2M dla EmployeeTask. Możesz użyć sprzężenia krzyżowego, aby przypisać każde zadanie każdemu podanemu pracownikowi, zakładając, że przekształciłeś csv w zmienne tabeli (lub coś takiego).
SynBiotik


14

Zazwyczaj nie będziesz potrzebować pełnego produktu kartezjańskiego dla większości zapytań do baz danych. Cała siła relacyjnych baz danych polega na tym, że możesz zastosować dowolne ograniczenia, które mogą Cię zainteresować, aby uniknąć pobierania niepotrzebnych wierszy z bazy danych.

Przypuszczam, że jeden wymyślony przykład, w którym możesz chcieć, to sytuacja, gdy masz tabelę pracowników i tabelę prac, które wymagają wykonania i chcesz zobaczyć wszystkie możliwe przydziały jednego pracownika do jednej pracy.


11

Ok, to prawdopodobnie nie odpowie na pytanie, ale jeśli to prawda (a nie jestem tego nawet pewien), to fajna historia.

We wczesnych latach istnienia Oracle, jeden z programistów zdał sobie sprawę, że musi zduplikować każdy wiersz w tabeli (na przykład możliwe jest, że była to tabela zdarzeń i musiał ją zmienić osobno „zdarzenie początkowe” i „zdarzenie końcowe” wpisy). Uświadomił sobie, że gdyby miał tabelę z zaledwie dwoma wierszami, mógłby wykonać sprzężenie krzyżowe, wybierając tylko kolumny w pierwszej tabeli i uzyskać dokładnie to, czego potrzebuje. Stworzył więc prosty stół, który naturalnie nazwał „DUAL”.

Później musiał zrobić coś, co można było zrobić tylko poprzez wybór z tabeli, mimo że sama czynność nie miała nic wspólnego ze stołem (być może zapomniał o zegarku i chciał odczytać godzinę za pomocą opcji SELECT SYSDATE FROM ... .) Uświadomił sobie, że nadal ma swój stół DUAL leżący w pobliżu i użył tego. Po chwili miał dość podwójnego drukowania czasu, więc w końcu usunął jeden z wierszy.

Inni w Oracle zaczęli używać jego tabeli i ostatecznie zdecydowano się włączyć go do standardowej instalacji Oracle.

To wyjaśnia, dlaczego tabela, której jedynym znaczeniem jest to, że ma jeden wiersz, ma nazwę oznaczającą „dwa”.


8

Kluczem jest „pokaż mi wszystkie możliwe kombinacje”. Użyłem ich w połączeniu z innymi polami obliczeniowymi, a następnie posortowałem / przefiltrowałem je.

Załóżmy na przykład, że tworzysz aplikację arbitrażową (handlową). Masz sprzedawców oferujących produkty po określonej cenie, a kupujących proszących o produkty po określonej cenie. Wykonujesz sprzężenie krzyżowe w kluczu produktu (aby dopasować potencjalnych kupujących i sprzedających), obliczasz różnicę między kosztem a ceną, a następnie sortujesz malejąco. na tym, aby dać tobie (pośrednikowi) najbardziej dochodowe transakcje do wykonania. Prawie zawsze będziesz mieć oczywiście inne kryteria filtru ograniczającego.


Ach! To wyjaśnienie jest dla mnie najbardziej sensowne. W takim przypadku WEWNĘTRZNE DOŁĄCZENIE nie ma sensu, ponieważ nie ma związku między identyfikatorem produktu a sprzedawcą, ponieważ wielu sprzedawców może sprzedawać ten sam produkt.
moonman239

3

Przyjmuje coś w rodzaju tabeli cyfr, która ma dziesięć wierszy na cyfry 0-9. Możesz użyć sprzężenia krzyżowego na tej tabeli kilka razy, aby uzyskać wynik, który ma dowolną liczbę potrzebnych wierszy, a wyniki są odpowiednio ponumerowane. Ma to wiele zastosowań. Na przykład możesz połączyć to z funkcją datadd (), aby uzyskać zestaw na każdy dzień w danym roku.



1

Wyobraź sobie, że masz serię zapytań, które chcesz skierować do określonej kombinacji pozycji i dat (ceny, dostępność itp.). Możesz załadować elementy i daty do oddzielnych tabel tymczasowych, a zapytania krzyżować się z tabelami. Może to być wygodniejsze niż alternatywa polegająca na wyliczaniu pozycji i dat w klauzulach IN, zwłaszcza że niektóre bazy danych ograniczają liczbę elementów w klauzuli IN.


1

możesz go użyć CROSS JOIN do: - generowania danych do celów testowych - łączenia wszystkich właściwości - potrzebujesz wszystkich możliwych kombinacji np. grup krwi (A, B, ...) z Rh - / +, itd ... - strojenia do Twoich celów;) - nie jestem ekspertem w tej dziedzinie;)

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;
  • utwórz łączenie dla 2 tabel bez wspólnego identyfikatora, a następnie pogrupuj je przy użyciu funkcji max (), itp., aby znaleźć najwyższą możliwą kombinację
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.