2013-10-02 93 views
1

我試圖下面的查詢,帶外連接的遞歸查詢?

DECLARE @EntityType varchar(25) 
SET @EntityType = 'Accessory'; 

WITH Entities (
     E_ID, E_Type, 
     P_ID, P_Name, P_DataType, P_Required, P_OnlyOne, 
     PV_ID, PV_Value, PV_EntityID, PV_ValueEntityID, 
     PV_UnitValueID, PV_UnitID, PV_UnitName, PV_UnitDesc, PV_MeasureID, PV_MeasureName, PV_UnitValue, 
     PV_SelectionID, PV_DropDownID, PV_DropDownName, PV_DropDownOptionID, PV_DropDownOptionName, PV_DropDownOptionDesc, 
     RecursiveLevel 
    ) 
AS 
(
    -- Original Query 
    SELECT dbo.Entity.ID AS E_ID, dbo.EntityType.Name AS E_Type, 
    dbo.Property.ID AS P_ID, dbo.Property.Name AS P_Name, DataType.Name AS P_DataType, Required AS P_Required, OnlyOne AS P_OnlyOne, 
    dbo.PropertyValue.ID AS PV_ID, dbo.PropertyValue.Value AS PV_Value, dbo.PropertyValue.EntityID AS PV_EntityID, dbo.PropertyValue.ValueEntityID AS PV_ValueEntityID, 
    dbo.UnitValue.ID AS PV_UnitValueID, dbo.UnitOfMeasure.ID AS PV_UnitID, dbo.UnitOfMeasure.Name AS PV_UnitName, dbo.UnitOfMeasure.Description AS PV_UnitDesc, dbo.Measure.ID AS PV_MeasureID, dbo.Measure.Name AS PV_MeasureName, dbo.UnitValue.UnitValue AS PV_UnitValue, 
    dbo.DropDownSelection.ID AS PV_SelectionID, dbo.DropDown.ID AS PV_DropDownID, dbo.DropDown.Name AS PV_DropDownName, dbo.DropDownOption.ID AS PV_DropDownOptionID, dbo.DropDownOption.Name AS PV_DropDownOptionName, dbo.DropDownOption.Description AS PV_DropDownOptionDesc, 
    0 AS RecursiveLevel 
    FROM dbo.Entity 
    INNER JOIN dbo.EntityType ON dbo.EntityType.ID = dbo.Entity.TypeID 
    INNER JOIN dbo.Property ON dbo.Property.EntityTypeID = dbo.Entity.TypeID 
    INNER JOIN dbo.PropertyValue ON dbo.Property.ID = dbo.PropertyValue.PropertyID AND dbo.PropertyValue.EntityID = dbo.Entity.ID 
    INNER JOIN dbo.DataType ON dbo.DataType.ID = dbo.Property.DataTypeID 
    LEFT JOIN dbo.UnitValue ON dbo.UnitValue.ID = dbo.PropertyValue.UnitValueID 
    LEFT JOIN dbo.UnitOfMeasure ON dbo.UnitOfMeasure.ID = dbo.UnitValue.UnitOfMeasureID 
    LEFT JOIN dbo.Measure ON dbo.Measure.ID = dbo.UnitOfMeasure.MeasureID 
    LEFT JOIN dbo.DropDownSelection ON dbo.DropDownSelection.ID = dbo.PropertyValue.DropDownSelectedID 
    LEFT JOIN dbo.DropDownOption ON dbo.DropDownOption.ID = dbo.DropDownSelection.SelectedOptionID 
    LEFT JOIN dbo.DropDown ON dbo.DropDown.ID = dbo.DropDownSelection.DropDownID 
    WHERE dbo.EntityType.Name = @EntityType 
    UNION ALL 
    -- Recursive Query? 
    SELECT E2.E_ID AS E_ID, dbo.EntityType.Name AS E_Type, 
    dbo.Property.ID AS P_ID, dbo.Property.Name AS P_Name, DataType.Name AS P_DataType, Required AS P_Required, OnlyOne AS P_OnlyOne, 
    dbo.PropertyValue.ID AS PV_ID, dbo.PropertyValue.Value AS PV_Value, dbo.PropertyValue.EntityID AS PV_EntityID, dbo.PropertyValue.ValueEntityID AS PV_ValueEntityID, 
    dbo.UnitValue.ID AS PV_UnitValueID, dbo.UnitOfMeasure.ID AS PV_UnitID, dbo.UnitOfMeasure.Name AS PV_UnitName, dbo.UnitOfMeasure.Description AS PV_UnitDesc, dbo.Measure.ID AS PV_MeasureID, dbo.Measure.Name AS PV_MeasureName, dbo.UnitValue.UnitValue AS PV_UnitValue, 
    dbo.DropDownSelection.ID AS PV_SelectionID, dbo.DropDown.ID AS PV_DropDownID, dbo.DropDown.Name AS PV_DropDownName, dbo.DropDownOption.ID AS PV_DropDownOptionID, dbo.DropDownOption.Name AS PV_DropDownOptionName, dbo.DropDownOption.Description AS PV_DropDownOptionDesc, 
    (RecursiveLevel + 1) 
    FROM Entities AS E2 
    INNER JOIN dbo.Entity ON dbo.Entity.ID = E2.PV_ValueEntityID 
    INNER JOIN dbo.EntityType ON dbo.EntityType.ID = dbo.Entity.TypeID 
    INNER JOIN dbo.Property ON dbo.Property.EntityTypeID = dbo.Entity.TypeID 
    INNER JOIN dbo.PropertyValue ON dbo.Property.ID = dbo.PropertyValue.PropertyID AND dbo.PropertyValue.EntityID = E2.E_ID 
    INNER JOIN dbo.DataType ON dbo.DataType.ID = dbo.Property.DataTypeID 
    INNER JOIN dbo.UnitValue ON dbo.UnitValue.ID = dbo.PropertyValue.UnitValueID 
    INNER JOIN dbo.UnitOfMeasure ON dbo.UnitOfMeasure.ID = dbo.UnitValue.UnitOfMeasureID 
    INNER JOIN dbo.Measure ON dbo.Measure.ID = dbo.UnitOfMeasure.MeasureID 
    INNER JOIN dbo.DropDownSelection ON dbo.DropDownSelection.ID = dbo.PropertyValue.DropDownSelectedID 
    INNER JOIN dbo.DropDownOption ON dbo.DropDownOption.ID = dbo.DropDownSelection.SelectedOptionID 
    INNER JOIN dbo.DropDown ON dbo.DropDown.ID = dbo.DropDownSelection.DropDownID 

) 
SELECT E_ID, E_Type, 
    P_ID, P_Name, P_DataType, P_Required, P_OnlyOne, 
    PV_ID, PV_Value, PV_EntityID, PV_ValueEntityID, 
    PV_UnitValueID, PV_UnitID, PV_UnitName, PV_UnitDesc, PV_MeasureID, PV_MeasureName, PV_UnitValue, 
    PV_SelectionID, PV_DropDownID, PV_DropDownName, PV_DropDownOptionID, PV_DropDownOptionName, PV_DropDownOptionDesc, 
    RecursiveLevel 
FROM Entities 
INNER JOIN [dbo].[Entity] AS dE 
    ON dE.ID = PV_EntityID 

的問題是第二個查詢中,「遞歸一個」越來越我希望因爲我不能做LEFT JOIN的像在第一個查詢中的數據。 (至少在我的理解)。

如果我刪除了需要LEFT(外部)JOIN的數據獲取,那麼遞歸完美地工作。我的問題是我需要兩個。有什麼辦法可以完成這個嗎?

回答

3

http://msdn.microsoft.com/en-us/library/ms175972.aspx在遞歸CTE中不能有左/右/外連接。

對於遞歸CTE,您不能使用子查詢,因此我會按照this example獲取。

他們使用兩個CTE。第一個不是遞歸的,而是左連接來獲取它需要的數據。第二個CTE是第一個CTE的遞歸和內部連接。由於CTE1不是遞歸的,因此它可以爲缺失的行保留連接並提供缺省值,並保證可以在內部連接中工作。

但是,您也可以使用聯合和子選擇複製左連接,雖然它通常並不真正有用,但它很有趣。

在這種情況下,你會保持你的第一條語句是怎麼回事。它將匹配所有成功加入的行。

然後UNION與另一個查詢,消除連接查詢,但有一個

NOT EXISTS(SELECT 1 FROM MISSING_ROWS_TABLE WHERE MAIN_TABLE.JOIN_CONDITION = MISSING_ROWS_TABLE.JOIN_CONDITION) 

這得到失敗查詢1.前面的連接條件,可隨時更換,你會從獲得colmuns的所有行帶NULL的MISSING_ROWS_TABLE。我必須使用不支持外部連接的編碼框架來完成此操作。由於遞歸CTE不允許子查詢,所以你必須使用第一個解決方案。

+0

花了一個小時弄清楚爲什麼我得到一個無限遞歸循環,但我明白了。非常感謝,從來不會一個人想出來。 – Shelby115