Quelles sont les utilisations de Cross Join?

105

Une jointure croisée effectue un produit cartésien sur les tuples des deux ensembles.

SELECT *
FROM Table1
CROSS JOIN Table2

Dans quelles circonstances une telle opération SQL est-elle particulièrement utile?

Llyle
la source
36
C'est vraiment triste que cette question soit close. Je pense que cela pourrait être marqué Community Wiki, mais dire que ce n'est pas constructif est injuste.
Wayne Koorts
1
Je suis d'accord. Cela a répondu à la question exacte que j'avais.
Hadès
10
Il y a des moments où un développeur plus récent a du mal à comprendre les implications de certaines fonctions du logiciel qu'il utilise. Des questions comme celle-ci sont particulièrement utiles aux nouveaux développeurs, principalement parce que la discussion qui suit éclaire de nombreuses possibilités que les développeurs juniors n'ont jamais envisagées. Le format de la question est élémentaire, au mieux, mais l'intention semble être honnête en ce qu'elle demande «pourquoi cela existe-t-il même? Je suis d'accord avec Wayne Koorts, c'est dommage que casperOne ait choisi de fermer cela et l'a qualifié de «non constructif». La partie "non constructive" me dérange particulièrement.
Kaorie

Réponses:

93

Si vous avez une "grille" que vous souhaitez remplir complètement, comme les informations de taille et de couleur pour un vêtement particulier:

select 
    size,
    color
from
    sizes CROSS JOIN colors

Vous souhaitez peut-être une table contenant une ligne pour chaque minute de la journée et vous souhaitez l'utiliser pour vérifier qu'une procédure a été exécutée chaque minute, vous pouvez donc traverser trois tables:

select
    hour,
    minute
from
    hours CROSS JOIN minutes

Ou vous disposez d'un ensemble de spécifications de rapport standard que vous souhaitez appliquer chaque mois de l'année:

select
    specId,
    month
from
    reports CROSS JOIN months

Le problème avec le maintien de ces vues sous forme de vues est que dans la plupart des cas, vous ne voulez pas d'un produit complet, en particulier en ce qui concerne les vêtements. Vous pouvez ajouter une MINUSlogique à la requête pour supprimer certaines combinaisons que vous ne portez pas, mais vous trouverez peut-être plus facile de remplir une table d'une autre manière et de ne pas utiliser de produit cartésien.

En outre, vous pourriez finir par essayer la jointure croisée sur des tables qui ont peut-être quelques lignes de plus que vous ne le pensiez, ou peut-être que votre WHEREclause était partiellement ou complètement manquante. Dans ce cas, votre DBA vous informera rapidement de l'omission. Habituellement, il ou elle ne sera pas heureux.

Dave DuPlantis
la source
5
... Dans ce cas, votre DBA vous informera rapidement de l'omission. Habituellement, il ou elle ne sera pas heureux. ... haha, si vrai!
RSW
2
@Dave: Le deuxième exemple ne sera-t-il pas que des minutes CROSS JOIN?
Rakesh
@Rakesh, bonne prise, je pensais à autre chose que ce que je tapais. Fixé.
Dave DuPlantis
1
J'imagine qu'une jointure croisée est très pratique si on vous donnait 2 ensembles d'identifiants (peut-être au format csv), un ensemble contiendrait les identifiants d'employés et l'autre contiendrait les identifiants de tâche. L'idée est que vous disposez d'une table M2M pour EmployeeTask. Vous pouvez utiliser la jointure croisée pour attribuer chaque tâche donnée à chaque employé donné, à condition que vous ayez transformé le csv en variables de table (ou quelque chose).
SynBiotik
20

Générez des données pour les tests.

Ovidiu Pacurar
la source
Je n'ai jamais pensé que je verrais une «réponse» de 4 mots recevoir 9 votes positifs.
mickmackusa
14

Vous ne souhaiterez généralement pas un produit cartésien complet pour la plupart des requêtes de base de données. Toute la puissance des bases de données relationnelles est que vous pouvez appliquer toutes les restrictions qui vous intéressent pour vous permettre d'éviter d'extraire des lignes inutiles de la base de données.

Je suppose qu'un exemple artificiel où vous pourriez souhaiter cela est si vous avez un tableau des employés et un tableau des emplois à faire et que vous voulez voir toutes les affectations possibles d'un employé à un travail.

Excité
la source
11

Ok, cela ne répondra probablement pas à la question, mais si c'est vrai (et je n'en suis même pas sûr), c'est un peu d'histoire.

Au début d'Oracle, l'un des développeurs s'est rendu compte qu'il avait besoin de dupliquer chaque ligne d'une table (par exemple, il est possible que ce soit une table d'événements et qu'il ait dû la changer séparément "événement de début" et "événement de fin". entrées). Il s'est rendu compte que s'il avait une table avec seulement deux lignes, il pourrait faire une jointure croisée, en sélectionnant uniquement les colonnes de la première table, et obtenir exactement ce dont il avait besoin. Il a donc créé une table simple, qu'il a naturellement appelée "DUAL".

Plus tard, il doit faire quelque chose qui ne peut être fait que via une sélection dans une table, même si l'action elle-même n'a rien à voir avec la table, (peut-être qu'il a oublié sa montre et voulait lire l'heure via SELECT SYSDATE FROM .. .) Il s'est rendu compte qu'il avait toujours sa table DUAL traîner et l'a utilisé. Au bout d'un moment, il en avait assez de voir l'heure imprimée deux fois, alors il a finalement supprimé l'une des lignes.

D'autres chez Oracle ont commencé à utiliser sa table, et finalement, il a été décidé de l'inclure dans l'installation standard d'Oracle.

Ce qui explique pourquoi une table dont la seule signification est qu'elle comporte une ligne a un nom qui signifie «deux».

James Curran
la source
8

La clé est "montre-moi toutes les combinaisons possibles". Je les ai utilisés en conjonction avec d'autres champs calculés, puis les ai triés / filtrés.

Par exemple, supposons que vous construisez une application d'arbitrage (trading). Vous avez des vendeurs qui proposent des produits à un prix et des acheteurs qui demandent des produits à un coût. Vous effectuez une jointure croisée sur la clé de produit (pour faire correspondre les acheteurs et les vendeurs potentiels), calculez l'écart entre le coût et le prix, puis triez desc. sur ceci pour vous donner (l'intermédiaire) les métiers les plus rentables à exécuter. Vous aurez presque toujours d'autres critères de filtrage limitatifs bien sûr.

Kevin Dostalek
la source
Ah! Cette explication me paraît la plus logique. Dans ce cas, un INNER JOIN n'a aucun sens car il n'y a pas de relation entre un identifiant de produit et un vendeur, car plusieurs vendeurs peuvent vendre le même produit.
moonman239
3

Prend quelque chose comme une table de chiffres, qui a dix lignes pour les chiffres 0-9. Vous pouvez utiliser la jointure croisée sur cette table plusieurs fois pour obtenir un résultat contenant le nombre de lignes dont vous avez besoin, avec les résultats numérotés de manière appropriée. Cela a un certain nombre d'utilisations. Par exemple, vous pouvez le combiner avec une fonction datadd () pour obtenir un ensemble pour chaque jour d'une année donnée.

Joel Coehoorn
la source
1

Imaginez que vous ayez une série de requêtes que vous souhaitez émettre sur une combinaison spécifique d'articles et de dates (prix, disponibilité, etc.). Vous pouvez charger les éléments et les dates dans des tables temporaires séparées et faire en sorte que vos requêtes rejoignent les tables. Cela peut être plus pratique que l'alternative d'énumérer les éléments et les dates dans les clauses IN, d'autant plus que certaines bases de données limitent le nombre d'éléments dans une clause IN.

complètement
la source
1

vous pouvez l'utiliser CROSS JOIN pour: - générer des données à des fins de test - combiner toutes les propriétés - vous avez besoin de toutes les combinaisons possibles, par exemple des groupes sanguins (A, B, ..) avec Rh - / +, etc ... - le régler pour vos besoins;) - Je ne suis pas expert dans ce domaine;)

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;
  • créez une jointure pour 2 tables sans identifiant commun puis groupez-la en utilisant max (), etc. pour trouver la combinaison la plus élevée possible
HankerPL
la source