簡體   English   中英

通過此MySql全外部聯接(或聯合)幫助我

[英]Help me out with this MySql full outer join (or union)

這來自將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中的表一樣可以訪問它? 如果表模式有幫助,請回復並添加評論,然后將其添加到問題中。

提前致謝!

通常可以使用LEFT JOINRIGHT JOINUNION來模擬FULL OUTER JOIN RIGHT JOIN 也就是說,它全部在左邊,右邊所有,在可能的情況下匹配加入條件。 根據我的經驗,它通常很少使用。 我有一個僅使用一次的大型系統。

您可能要在這里做的事情是因為FULL OUTER JOIN不可用,這是對UNION兩個設置,並在兩個子集之間設置一些JOIN條件,這實際上是不可能的。 您的示例中為UNION的兩個集合不能具有別名,也不能具有試圖鏈接它們的WHERE子句。

上面描述的方法將左右外部聯接結合在一起,效果很好,並且似乎是公認的解決方案。 但是,正如我在閱讀留言板上的各種示例時所發現的那樣,這里還有一些細節。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM