【问题标题】:Help me out with this MySql full outer join (or union)帮我解决这个 MySql 完全外部联接(或联合)
【发布时间】:2010-11-02 15:33:51
【问题描述】:

这来自将 MSSQL 转换为 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;

假设任何变量已经存在。这在“As SharedDataPerPath”部分出现问题,所以我猜测我给 select 语句加上别名,以便您可以像 MySQL 不支持表一样访问它?如果表架构有帮助,请回复评论,我会将其添加到问题中。

提前致谢!

【问题讨论】:

  • 您可以投票支持该功能的实现at MySql

标签: mysql union left-join inner-join outer-join


【解决方案1】:

上述将左右外连接联合在一起的方法效果很好,似乎是普遍接受的解决方案。但是,我在阅读留言板上的各种示例时发现了一些细节。

  1. 将用于连接的列上的表源从一个选择交换到另一个选择,以解决外部连接产生的 NULL。

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

【讨论】:

    【解决方案2】:
    -- 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;
    

    【讨论】:

      【解决方案3】:

      FULL OUTER JOIN 通常可以用LEFT JOINRIGHT JOINUNION 模拟。即它都在左边和右边,尽可能匹配连接条件。根据我的经验,它通常很少使用。我有一个只使用一次的大型系统。

      由于FULL OUTER JOIN 不可用,您似乎想要在这里做的是UNION 两组并在两个子集之间设置一些JOIN 标准,这确实是不可能的。在您的示例中,UNIONed 的两个集合不能有别名,也不能有尝试链接它们的 WHERE 子句。

      【讨论】:

      • 好吧,如果它不适用于 mysql,那很好,但这在 MSSQL 中是有效的,那么我该怎么做才能让它工作呢?我应该分解它并将一些东西存储在一些临时表中吗?
      • 您能否发布一个完整的可运行示例,其中 SQL Server 接受 UNION 不同部分之间的 JOINing 语法?
      猜你喜欢
      • 2017-06-09
      • 2013-12-17
      • 2011-07-26
      • 1970-01-01
      • 2017-08-04
      • 1970-01-01
      相关资源
      最近更新 更多