Aiutami con questo full outer join MySql (o unione)
-
13-09-2019 - |
Domanda
Questo è venuta da convertire MSSQL a MySQL. Quanto segue è il codice che sto cercando di mettersi al lavoro:
CREATE TEMPORARY TABLE PageIndex (
IndexId int AUTO_INCREMENT NOT NULL PRIMARY KEY,
ItemId VARCHAR(64)
);
INSERT INTO PageIndex (ItemId)
SELECT Paths.PathId
FROM Paths,
((SELECT Paths.PathId
FROM AllUsers, Paths
WHERE Paths.ApplicationId = @ApplicationId
AND AllUsers.PathId = Paths.PathId
AND (@Path IS NULL
OR Paths.LoweredPath LIKE LOWER(@Path))) AS SharedDataPerPath
UNION -- This used to be a FULL OUTER JOIN but MySQL doesnt support that.
(SELECT DISTINCT Paths.PathId
FROM PerUser, Paths
WHERE Paths.ApplicationId = @ApplicationId
AND PerUser.PathId = Paths.PathId
AND (@Path IS NULL
OR Paths.LoweredPath LIKE LOWER(@Path))) AS UserDataPerPath
ON SharedDataPerPath.PathId = UserDataPerPath.PathId)
WHERE Paths.PathId = SharedDataPerPath.PathId OR Paths.PathId = UserDataPerPath.PathId
ORDER BY Paths.Path ASC;
Si assuma tutte le variabili esistono già. Dove questo è rottura è sul 'Come SharedDataPerPath' parte, quindi sto cercando di indovinare che ho aliasing una dichiarazione prescelta in modo che vi si possa accedere come un tavolo non è supportata in MySQL? Se schema della tabella avrebbe aiutato, rispondere con un commento e vorrei aggiungere che alla domanda.
Grazie in anticipo!
Soluzione
-- Assuming these are defined in your store procedure
DECLARE @ApplicationId VARCHAR(64);
DECLARE @Path VARCHAR(256);
SET @ApplicationId = NULL;
Set @Path = NULL;
CREATE TEMPORARY TABLE SharedDataPerPath
(
PathId VARCHAR(256)
);
CREATE TABLE UserDataPerPath
(
PathId VARCHAR(256)
);
-- Do this instead of aliasing a select statment 'AS SharedDataPerPath'
INSERT INTO SharedDataPerPath
SELECT Paths.PathId
FROM aspnet_PersonalizationAllUsers AllUsers, aspnet_Paths Paths
WHERE Paths.ApplicationId = @ApplicationId
AND AllUsers.PathId = Paths.PathId
AND (@Path IS NULL OR Paths.LoweredPath LIKE LOWER(@Path));
-- Do this instead of aliasing a select statement 'AS UserDataPerPath'
INSERT INTO UserDataPerPath
SELECT DISTINCT Paths.PathId
FROM aspnet_PersonalizationPerUser PerUser, aspnet_Paths Paths
WHERE Paths.ApplicationId = @ApplicationId
AND PerUser.PathId = Paths.PathId
AND (@Path IS NULL OR Paths.LoweredPath LIKE LOWER(@Path));
-- This is how I would do my 'FULL OUTER JOIN'
SELECT Paths.PathId
FROM `wppi_net_db`.`aspnet_Paths` Paths,
(SELECT *
FROM SharedDataPerPath AS s
LEFT OUTER JOIN UserDataPerPath AS u
ON s.PathID = u.PathID
UNION -- OR UNION ALL see: http://www.xaprb.com/blog/2006/05/26/how-to-write-full-outer-join-in-mysql/
SELECT *
FROM SharedDataPerPath AS s
RIGHT OUTER JOIN UserDataPerPath AS u
ON s.PathID = u.PathID) AS DataPerPaths
WHERE Paths.PathId = DataPerPaths.PathId
ORDER BY Paths.Path ASC;
-- At some point you need to drop your temp tables
DROP TEMPORARY TABLE SharedDataPerPath;
DROP TEMPORARY TABLE UserDataPerPath;
Altri suggerimenti
Un FULL OUTER JOIN
spesso può essere simulato con il UNION
sia LEFT JOIN
e RIGHT JOIN
. cioè è tutto a sinistra e quelli di destra, corrispondente ove possibile sui criteri aderire. Di solito è molto raramente utilizzato, nella mia esperienza. Ho un grande sistema in cui viene utilizzato solo una volta.
Cosa ti sembra di essere voler fare qui perché FULL OUTER JOIN
non è disponibile è quello di UNION
due set e impostare alcuni criteri JOIN
tra i due sottoinsiemi, che non è davvero possibile. I due set che sono UNION
ed nel tuo esempio non possono avere alias, né possono avere una clausola WHERE
che tenta di collegarli.
Il metodo descritto sopra con quello esterno destro e sinistro si unisce unioned insieme funziona bene e sembra essere la soluzione comunemente accettata. Ci sono alcuni dettagli lasciati fuori da questo però come ho trovato durante la lettura vari esempi attraverso le bacheche.
-
Scambia le tue fonti di tabella sulle colonne da utilizzare per unirsi da una selezione per l'altro per tenere conto di Null prodotti dalla outer join.
-
Aggiungi funzioni COALESCE per i vostri "colonne fisse" che potrebbe anche tornare come Null prodotti dalla Join esterni.
Esempio:
SELECT
`Wins_VW`.`Year`,
`Wins_VW`.`Period`,
COALESCE(`Wins_VW`.`Wins`,0) as Wins,
COALESCE(`Leads_VW`.`Leads`,0) as Leads
FROM `Wins_VW` LEFT OUTER JOIN `Leads_VW`
ON( `Wins_VW`.`Year` = `Leads_VW`.`Year`
AND `Wins_VW`.`Period` = `Leads_VW`.`Period`)
UNION
SELECT
`Leads_VW`.`Year`,
`Leads_VW`.`Period`,
COALESCE(`Wins_VW`.`Wins`,0) as Wins,
COALESCE(`Leads_VW`.`Leads`,0) as Leads
FROM `Wins_VW` RIGHT OUTER JOIN `Leads_VW`
ON( `Wins_VW`.`Year` = `Leads_VW`.`Year`
AND `Wins_VW`.`Period` = `Leads_VW`.`Period`)