2011-06-06 39 views
2

目前我正在執行以下事項:如何分組這個SQL外連接查詢

SELECT SiteFeatures.SiteId, Blogs.FeatureInstance_Id as BlogId, 
     PageCollections.FeatureInstance_Id as PagesId, 
     Portfolios.FeatureInstance_Id as PortfolioId 
FROM SiteFeatures 
      LEFT OUTER JOIN Blogs 
       ON SiteFeatures.FeatureInstanceId = Blogs.FeatureInstance_id 
      LEFT OUTER JOIN Portfolios 
       ON SiteFeatures.FeatureInstanceId = Portfolios.FeatureInstance_id 
      LEFT OUTER JOIN PageCollections 
       ON SiteFeatures.FeatureInstanceId = PageCollections.FeatureInstance_id 

這會返回一個結果集,像這樣:

SiteId  BlogId  PagesId  PortfolioId 
1   1   NULL  NULL 
1   NULL  1   NULL 
1   NULL  NULL  1 
2   2   NULL  NULL 
2   NULL  2   NULL 
2   NULL  NULL  2 

這意味着我將不得不內聚合這些我的應用程序代碼我怎樣才能改變我的查詢(在考慮性能)返回:

SiteId  BlogId  PagesId  PortfolioId 
1   1   1   1 
1   2   2   2 

按照要求 - 我的架構:

dbdiagram

+2

你可以顯示你的表格結構和PK/FK關係嗎? – HLGEM 2011-06-06 16:25:08

+1

你需要使用左外連接嗎?您的示例數據似乎是另有說明。 – dpmattingly 2011-06-06 16:28:49

+2

對於給定的查詢,我無法想象我的生活如何獲得您的*初始*輸出。你確定你給我們的數據有代表性嗎? – 2011-06-06 16:46:52

回答

3
SELECT 
    S.SiteId, 
    B.FeatureInstance_Id BlogId, 
    P.FeatureInstance_Id PortfolioId, 
    C.FeatureInstance_Id PagesId 
FROM 
    Sites S 
    LEFT JOIN (
     SiteFeatures F1 
     INNER JOIN Blogs B ON F1.FeatureInstanceId = B.FeatureInstance_id 
    ) ON S.SiteID = F1.SiteID 
    LEFT JOIN (
     SiteFeatures F2 
     INNER JOIN Portfolios P ON F2.FeatureInstanceId = P.FeatureInstance_id 
    ) ON S.SiteID = F2.SiteID 
    LEFT JOIN (
     SiteFeatures F3 
     LEFT JOIN PageCollections C ON F3.FeatureInstanceId = C.FeatureInstance_id 
    ) ON S.SiteID = F3.SiteID 

這應該沒關係假設所有您的子表格每個FeatureInstance_Id只能有一行。

如果您設計了數據庫,您在表格中列名不一致的情況下在指關節上獲得了良好的說唱效果。 :)

如果該查詢工作,那麼你可以考慮在一系列的意見,將查詢返回一個不錯的緊湊型封裝的事情是:

CREATE VIEW BlogsFeature 
AS 
SELECT 
    F.* 
FROM 
    SiteFeatures F 
    WHERE EXISTS (-- or you could do an INNER JOIN, though in theory this is correct 
     SELECT 1 
     FROM Blogs B 
     WHERE F.FeatureInstanceId = B.FeatureInstance_id 
    ) 

這樣做的所有三個表將產生以下查詢:

SELECT 
    S.SiteId, 
    B.FeatureInstance_Id BlogId, 
    P.FeatureInstance_Id PortfolioId, 
    C.FeatureInstance_Id PagesId 
FROM 
    Sites S 
    LEFT JOIN BlogsFeature B ON S.SiteID = B.SiteID 
    LEFT JOIN PortfoliosFeature P ON S.SiteID = P.SiteID 
    LEFT JOIN PageCollections C O ON S.SiteID = C.SiteID 

其實,這使我想到另一種方式來表達你所需要的查詢,但它仍然不是很漂亮的前瞻性:

SELECT 
    S.SiteId, 
    F1.FeatureInstance_Id BlogId, 
    F2.FeatureInstance_Id PortfolioId, 
    F3.FeatureInstance_Id PagesId 
FROM 
    Sites S 
    LEFT JOIN SiteFeatures F1 
     ON S.SiteID = F1.SiteID 
     AND EXISTS (
     SELECT 1 FROM Blogs B 
     WHERE F1.FeatureInstanceId = B.FeatureInstance_id 
    ) 
    LEFT JOIN SiteFeatures F2 
     ON S.SiteID = F2.SiteID 
     AND EXISTS (
     SELECT 1 FROM Portfolios P 
     WHERE F2.FeatureInstanceId = P.FeatureInstance_id 
    ) 
    LEFT JOIN SiteFeatures F3 
     ON S.SiteID = F3.SiteID 
     AND EXISTS (
     SELECT 1 FROM PageCollections C 
     WHERE F3.FeatureInstanceId = C.FeatureInstance_id 
    ) 

如果您暫時將您的uniqueidentifiers轉換爲字符串,您仍然可以使用Max()方法。

SELECT 
    S.SiteId, 
    B.FeatureInstance_Id BlogId, 
    P.FeatureInstance_Id PortfolioId, 
    C.FeatureInstance_Id PagesId 
FROM 
    SiteFeatures F 
    INNER JOIN Blogs B ON 
+0

@Erik是的,我知道:)這只是一個概念證明,架構已經由NHibernate生成。完成這些測試後,我會正確地修正列名。 – 2011-06-06 22:39:22

+0

@Erik,與我原來的查詢中的6相比,它返回​​了54條記錄。 – 2011-06-06 22:47:34

+0

@Ben我更新了我的查詢。你可以再試一次嗎? – ErikE 2011-06-07 00:19:31

3
SELECT SiteFeatures.SiteId 
     , MAX(Blogs.FeatureInstance_Id) as BlogId 
     , MAX(PageCollections.FeatureInstance_Id) as PagesId 
     , MAX(Portfolios.FeatureInstance_Id) as PortfolioId 
FROM  SiteFeatures 
LEFT OUTER JOIN Blogs 
     ON SiteFeatures.FeatureInstanceId = Blogs.FeatureInstance_id 
LEFT OUTER JOIN Portfolios 
     ON SiteFeatures.FeatureInstanceId = Portfolios.FeatureInstance_id 
LEFT OUTER JOIN PageCollections 
     ON SiteFeatures.FeatureInstanceId = PageCollections.FeatureInstance_id 
GROUP BY SiteFeatures.SiteId 
ORDER BY SiteFeatures.SiteId ASC 
+0

謝謝你。不幸的是,這對我不起作用,因爲我的Id列是唯一的標識符(最大值不起作用)。這是我的錯,我應該包括更多關於我的模式的細節。無論如何。 – 2011-06-06 21:49:37

+0

@Ben,更新了答案。 – Johan 2011-06-06 21:55:54

+0

鑑於架構,在編輯中添加的查詢不正確。 – ErikE 2011-06-06 22:03:48

1

您是否嘗試過使用INNER JOIN秒且不LEFT JOIN S'

SELECT SiteFeatures.SiteId 
     , Blogs.FeatureInstance_Id as BlogId 
     , PageCollections.FeatureInstance_Id as PagesId 
     , Portfolios.FeatureInstance_Id as PortfolioId 
FROM SiteFeatures 
      INNER JOIN Blogs 
       ON SiteFeatures.FeatureInstanceId = Blogs.FeatureInstance_id 
      INNER JOIN Portfolios 
       ON SiteFeatures.FeatureInstanceId = Portfolios.FeatureInstance_id 
      INNER JOIN PageCollections 
       ON SiteFeatures.FeatureInstanceId = PageCollections.FeatureInstance_id 

關於第二個想法,這可能是你想要什麼:

SELECT sf.SiteId 
     , (SELECT b.FeatureInstance_Id 
      FROM Blogs AS b 
      WHERE sf.FeatureInstanceId = b.FeatureInstance_id 
     ) AS BlogId 
     , (SELECT pc.FeatureInstance_Id 
      FROM PageCollections AS pc 
      WHERE sf.FeatureInstanceId = pc.FeatureInstance_id 
     ) AS PagesId 
     , (SELECT p.FeatureInstance_Id 
      FROM Portfolios AS p 
      WHERE sf.FeatureInstanceId = p.FeatureInstance_id 
     ) AS PortfolioId 
FROM SiteFeatures AS sf 

在第三思想(而當看到被錄取了Eric的答覆後),我會做一個嘗試,只是爲了表明它可以(這樣的)子查詢來實現:

SELECT s.SiteId 
     , (SELECT b.FeatureInstance_Id 
      FROM Blogs AS b 
      JOIN SiteFeatures sf 
       ON sf.FeatureInstanceId = b.FeatureInstance_id 
      WHERE sf.SiteId = s.SiteId 
     ) AS BlogId 
     , (SELECT pc.FeatureInstance_Id 
      FROM PageCollections AS pc 
      JOIN SiteFeatures sf 
       ON sf.FeatureInstanceId = pc.FeatureInstance_id 
      WHERE sf.SiteId = s.SiteId 
     ) AS PagesId 
     , (SELECT p.FeatureInstance_Id 
      FROM Portfolios AS p 
      JOIN SiteFeatures sf 
       ON sf.FeatureInstanceId = p.FeatureInstance_id 
      WHERE sf.SiteId = s.SiteId 
     ) AS PortfolioId 
FROM Sites AS s 
+0

@Siva:糟糕,thnx。 – 2011-06-06 22:27:34

+0

@ypercube - 第一個查詢不會返回任何結果。一個網站有很多功能,但功能只有一個博客或投資組合或PageCollection。第二個查詢返回的結果與我原始發佈的查詢返回的結果相同。 – 2011-06-06 22:43:46

+0

@Ben:好的,然後@ Eric的答案似乎是你想要的。 (使用INNER JOIN而不是LEFT JOIN) – 2011-06-06 22:53:45

1

由於您使用的是SQL Server 2008,他re是使用CROSS APPLY可能適用於您的一種可能選項。這裏可能不是最好的選擇。我剛剛給了它一個鏡頭。

SELECT   SFR.SiteId 
      , BLG.FeatureInstance_Id AS BlogId 
      , PFL.FeatureInstance_Id AS PortfolioId 
      , PGC.FeatureInstance_Id AS PagesId 
FROM   dbo.SiteFeatures SFR 
CROSS APPLY  (
        SELECT 
        TOP 1 FeatureInstance_Id 
        FROM dbo.Blogs BLG 
        WHERE BLG.FeatureInstance_Id = SFR.FeatureInstanceId 
       ) BLG 
CROSS APPLY  (
        SELECT 
        TOP 1 FeatureInstance_Id 
        FROM dbo.PortFolios PFL 
        WHERE PFL.FeatureInstance_Id = SFR.FeatureInstanceId 
       ) PFL 
CROSS APPLY  (
        SELECT 
        TOP 1 FeatureInstance_Id 
        FROM dbo.PageCollections PGC 
        WHERE PGC.FeatureInstance_Id = SFR.FeatureInstanceId 
       ) PGC 
+0

有趣。這不會返回任何結果(如果只是交叉應用BLG,它會這樣做),但我明天將給予CROSS APPLY一次。 – 2011-06-06 22:56:52

+0

工作。但給我完全一樣,我的原始查詢:)也許我應該繼續在我的應用程序內進行聚合... – 2011-06-06 23:18:56