SQL-запрос для выбора дочернего - PullRequest
1 голос
/ 20 июля 2011

Я использую следующую хранимую процедуру для выбора всех дочерних единиц данного идентификатора единицы. Для each unit only one child есть и нет дочерних для наименьшей единицы

ALTER PROCEDURE [dbo].[UnitSelectChildByID] 
@company_ID INT,
@unit_ID INT

AS
BEGIN
DECLARE @parent INT
    SET @parent=@unit_ID
    DECLARE @temp TABLE(id int)
    WHILE((SELECT COUNT(*)  FROM tblUnit WHERE parent_ID=@parent) >0)
    BEGIN
    INSERT INTO @temp SELECT unit_ID FROM tblUnit WHERE parent_ID=@parent
    SET @parent=(SELECT unit_ID FROM tblUnit WHERE parent_ID=@parent) 
    END
    SELECT 
         unit_ID
         ,short_Name AS unit     
    FROM 
         tblUnit 
    WHERE 
        unit_ID IN (SELECT id FROM @temp) OR unit_ID=@unit_ID
END 

Это работает правильно. Что я хочу знать, есть ли лучший способ выбора дочерних единиц на avoiding while loop and table variable

Ответы [ 3 ]

2 голосов
/ 20 июля 2011

Похоже, вы используете рекурсию, для чего подходят CTE.

WITH Units (unit_ID, short_Name)
AS
(
    --initial select of the main parent
    Select unit_ID, short_Name
    From tblUnit
    Where unit_ID = @unit_ID

    Union All

    --plus the recursive self join of the sub units
    Select unit_ID, short_Name
    From tblUnit
    Inner Join Units On Units.unit_ID = tblUnit.parent_ID
)

Select unit_ID, short_Name
From Units
1 голос
/ 20 июля 2011

Вы можете взглянуть на общие выражения таблиц http://msdn.microsoft.com/en-us/library/ms186243.aspx

Обратите внимание, что на самом деле я не пробовал приведенный ниже SQL, я просто изменил пример на странице MSDN, чтобы использовать определения таблиц и столбцов.

WITH UnitChildren (unit_ID, short_Name)
AS
(
-- Anchor member definition
    SELECT u.unit_ID, short_Name, 0 AS Level
    FROM tblUnit AS u
    WHERE unit_ID = @unit_ID
    UNION ALL
-- Recursive member definition
    SELECT u.unit_ID, short_Name, Level + 1
    FROM tblUnit AS u
    INNER JOIN UnitChildren AS uc
        ON u.unit_ID = uc.parent_ID
)

-- Statement that executes the CTE
SELECT * FROM UnitChildren 
GO
0 голосов
/ 20 июля 2011

Если в проекте только два уровня в иерархии:

SELECT    u.unit_ID, u.short_Name
FROM      tblUnit AS u LEFT OUTER JOIN
              tblUnit AS p ON u.parent_ID = p.unit_ID
WHERE     ISNULL(u.parent_ID, u.unit_ID) = @unit_ID
...