Home > Software engineering >  SQL join showing all combinaisons
SQL join showing all combinaisons

Time:02-23

I want a "join" that gives me every category (cat) and every site (cat_sites) knowing if they are associated to each other or not

CREATE TABLE cat (
  cat varchar(34) CHARACTER SET utf8 DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

CREATE TABLE cat_sites (
  cat varchar(34) CHARACTER SET utf8 DEFAULT NULL,
  site varchar(2) DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Having the following values:

INSERT INTO `cat` VALUES (''),('Autobus - Autocar'),('Camion / Tracteur de semi-remorque'),('Camionette'),('Motocycle'),('Remorque <3,5'),('Remorque >3,5'),('Tracteur'),('Tricycle / Quadricycle'),('Véhicule spécial'),('Voiture');

INSERT INTO `cat_sites` VALUES ('','EA'),('','MA'),('','SW'),('Autobus - Autocar','BI'),('Autobus - Autocar','LI'),('Autobus - Autocar','SW'),('Camion / Tracteur de semi-remorque','BI'),('Camion / Tracteur de semi-remorque','EA'),('Camion / Tracteur de semi-remorque','LI'),('Camion / Tracteur de semi-remorque','MA'),('Camion / Tracteur de semi-remorque','SW'),('Camionette','BI'),('Camionette','EA'),('Camionette','LI'),('Camionette','MA'),('Camionette','SW'),('Motocycle','BI'),('Motocycle','EA'),('Motocycle','MA'),('Motocycle','SW'),('Remorque <3,5','BI'),('Remorque <3,5','EA'),('Remorque <3,5','LI'),('Remorque <3,5','MA'),('Remorque <3,5','SW'),('Remorque >3,5','BI'),('Remorque >3,5','EA'),('Remorque >3,5','LI'),('Remorque >3,5','SW'),('Tracteur','BI'),('Tracteur','EA'),('Tracteur','LI'),('Tracteur','MA'),('Tracteur','SW'),('Tricycle / Quadricycle','BI'),('Tricycle / Quadricycle','EA'),('Tricycle / Quadricycle','MA'),('Tricycle / Quadricycle','SW'),('Véhicule spécial','BI'),('Véhicule spécial','LI'),('Voiture','BI'),('Voiture','EA'),('Voiture','LI'),('Voiture','MA'),('Voiture','SW');

cat:

enter image description here

cat_sites:

enter image description here

The following query is almost exactly what I am looking for:

SELECT * FROM cat  LEFT JOIN cat_sites ON cat.cat = cat_sites.cat

The problem is, that I do get all categories, but only the sites actually assoicated to the given categories. For example "Autobus - Autocar" is only available in "BI", "LI" and "SW", but not in "EA" and "MA".

enter image description here

What I would like to see are records with c1="Autobus - Autocar" and the missing sites having c2 with null values.

I could get a result by passing by an intermediaire query which would give me all possible combinations:

SELECT cat.cat, site.site FROM cat 
RIGHT OUTER JOIN (select distinct site from cat_sites) AS site ON 1=1

The final query would then be something like this:

SELECT cat_allsites.cat c1, cat_allsites.site, cat_sites.cat c2
FROM
(
SELECT cat.cat, site.site FROM cat 
RIGHT OUTER JOIN (select distinct site from cat_sites) AS site ON 1=1
) as cat_allsites
LEFT JOIN cat_sites ON cat_allsites.cat = cat_sites.cat

WHERE cat_allsites.cat="Autobus - Autocar"
group by cat_allsites.cat , cat_allsites.site, cat_sites.cat 
;

Anyone have a better idea on how to do this?

CodePudding user response:

You would normally cross join two sets to find all possible combinations, then use a left join to find matching/missing values:

select cat.cat, sites.site, cat_sites.*
from cat
cross join (select distinct site from cat_sites) as sites
left join cat_sites on cat.cat = cat_sites.cat and sites.site = cat_sites.site
  • Related