2009-06-13 9 views
-1

Cela vient de la conversion de MSSQL en MySQL. Ce qui suit est le code que j'essaie de mettre au travail:Aidez-moi avec cette jointure externe complète MySql (ou union)

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; 

Supposons que des variables existent déjà. Où cela casse est sur la partie 'As SharedDataPerPath', donc je devine que je alias une instruction select afin que vous puissiez y accéder comme une table n'est pas supportée par MySQL? Si le schéma de la table peut aider, répondez par un commentaire et je l'ajouterai à la question.

Merci d'avance!

+0

Vous pouvez voter pour cette fonction à mettre en œuvre [à MySql] (http://bugs.mysql.com/bug.php?id=18003&thanks=3¬ify=67 –

Répondre

1
-- 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; 
2

Un FULL OUTER JOIN peut souvent être simulé avec le UNION des deux LEFT JOIN et RIGHT JOIN. c'est-à-dire que tout est sur la gauche et ceux sur la droite, correspondant si possible aux critères de jointure. Il est généralement très rarement utilisé, selon mon expérience. J'ai un grand système où il n'est utilisé qu'une seule fois.

Ce que vous semblez vouloir le faire ici parce que FULL OUTER JOIN n'est pas disponible est de UNION deux ensembles et définir des critères JOIN entre les deux sous-ensembles, ce qui est vraiment pas possible. Les deux ensembles qui sont UNION ed dans votre exemple ne peuvent pas avoir d'alias, ni ne peuvent avoir une clause WHERE qui tente de les lier.

+0

ok bien c'est bien si ça ne marche pas pour mysql mais c'est valide en MSSQL, alors que puis-je faire pour que ça marche? Dois-je le décomposer et stocker des choses dans certaines tables temporaires? – DJTripleThreat

+0

Pouvez-vous publier un exemple exécutable complet dans lequel SQL Server accepte la syntaxe JOINING entre différentes sections de UNION? –

1

La méthode décrite ci-dessus avec les jointures externes gauche et droite unies ensemble fonctionne bien et semble être la solution communément acceptée. Cependant, il y a quelques détails qui restent, comme je l'ai constaté en lisant divers exemples à travers les forums.

  1. Swap vos sources de table sur les colonnes que vous utilisez pour se joindre à d'une sélection à l'autre pour tenir compte des valeurs NULL produites par jointures externes.

  2. Ajoutez des fonctions COALESCE à vos "colonnes fixes" qui pourraient aussi revenir en tant que valeurs NULL produites par les jointures externes.

Exemple:

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`) 
Questions connexes