繁体   English   中英

带有外部联接的递归查询?

[英]Recursive query with outer joins?

我正在尝试以下查询,

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的数据的获取,则递归可以完美地工作。 我的问题是我两个都需要。 有没有办法可以做到这一点?

根据http://msdn.microsoft.com/zh-cn/library/ms175972.aspx,您不能在递归CTE中具有左/右/外部联接。

对于递归CTE,您也不能使用子查询,因此我遵循这个例子

他们使用两个CTE。 第一个不是递归的,并且进行左连接以获得所需的数据。 第二个CTE是递归的,并且在第一个CTE上进行内部联接。 由于CTE1不是递归的,因此它可以保留联接并为缺少的行提供默认值,并确保在内部联接中工作。

但是,您也可以使用并集和子选择来复制左联接,尽管通常并没有用,但是很有趣。

在这种情况下,您将保留第一个语句的状态。 它将匹配所有成功加入的行。

然后将该查询与另一个删除该联接但具有一个

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

这将获取所有在查询1中未通过上一个联接条件的行。您可以使用NULL替换从MISSING_ROWS_TABLE获得的列。 一旦使用了不支持外部联接的编码框架,我就不得不这样做。 由于递归CTE不允许子查询,因此您必须使用第一个解决方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM