2009-06-13 18 views
-1

这是从MSSQL转换到MySql。以下是我试图开始工作的代码:帮我用这个MySql完全外连接(或联合)

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; 

假设任何变量已存在。如果这是破坏是在'作为SharedDataPerPath'的一部分,所以我猜我滥用选择语句,以便您可以像MySQL中不支持表一样访问它?如果表格模式有帮助,请回复评论,我会将其添加到问题中。

在此先感谢!

+0

可以投给此功能来实现[MySQL的](http://bugs.mysql.com/bug.php?id=18003&thanks=3¬ify=67 ) – 2012-06-11 14:44:13

回答

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

A FULL OUTER JOIN通常可以使用LEFT JOINRIGHT JOIN两者的UNION进行模拟。即全部在左边和右边,在可能的情况下匹配加入标准。根据我的经验,它通常极少使用。我有一个大系统,它只用了一次。

你似乎是想在这里做,因为FULL OUTER JOIN不适什么是UNION两套,并设置两个子集,这真的是不可能的之间的一些JOIN标准。在您的示例中编辑的UNION这两组不能有别名,也不能有WHERE子句试图链接它们。

+0

好吧,那很好,如果它不适用于MySQL,但这是在MSSQL中有效,那么我能做些什么来得到这个工作?我应该分解它,并在一些临时表中存储一些东西吗? – DJTripleThreat 2009-06-13 03:31:31

1

上面描述的将左右外连接结合在一起的方法运作良好,似乎是普遍接受的解决方案。不过,我留下了一些细节,因为我在阅读各种留言板上的各种示例时发现了这些细节。

  1. 将您用于连接的列的表源切换到另一个选择以解释由外部连接产生的空值。

  2. 将COALESCE函数添加到您的“固定列”中,这些列可能会返回为由外部联接产生的NULL。

实施例:

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