sql >> データベース >  >> RDS >> Sqlserver

SQL Server CTE 左外部結合

    階層にいくつのレベルがあるかわからない場合は?

    次に、このようなチャレンジは、再帰的 CTE を介して行われることがよくあります。

    スニペットの例:

    --
    -- Using table variables for testing reasons
    --
    declare @customertest table (cid int primary key, upid int);
    declare @conftest table (cid int, confname varchar(6) default 'budget', confvalue int);
    --
    -- Sample data
    --
    insert into @customertest (cid, upid) values 
    (1,0), (2,1), (3,1), (4,2), (5,2), (6,3), 
    (7,5), (8,5), (9,8), (10,9);
    insert into @conftest (cid, confvalue) values 
    (1,1000), (2,700), (3,300), (4,100), (5,200), (6,300);
    
    -- The customer that has his own budget, or not.
    declare @customerID int = 10;
    
    ;with RCTE AS 
    (
      --
      -- the recursive CTE starts from here. The seed records, as one could call it.
      --
      select cup.cid as orig_cid, 0 as lvl, cup.cid, cup.upid, budget.confvalue
      from @customertest as cup
      left join @conftest budget on (budget.cid = cup.cid and budget.confname = 'budget')
      where cup.cid = @customerID -- This is where we limit on the customer
    
      union all
    
      --
      -- This is where the Recursive CTE loops till it finds nothing new
      --
      select RCTE.orig_cid, RCTE.lvl+1, cup.cid, cup.upid, budget.confvalue
      from RCTE
      join @customertest as cup on (cup.cid = RCTE.upid)
      outer apply (select b.confvalue from @conftest b where b.cid = cup.cid and b.confname = 'budget') as budget
      where RCTE.confvalue is null -- Loop till a budget is found
    )
    select 
     orig_cid as cid, 
     confvalue
    from RCTE
    where confvalue is not null;    
    

    結果:

    cid confvalue
    --- ---------
     10       200
    

    ところで、MS SQL Server では LEFT OUTER JOIN の使用が許可されていないため、再帰的 CTE は OUTER APPLY を使用します。

    そして、予算のある upid に最大 1 レベルの深さがあることが確実である場合は?
    その場合は、単純な左結合と合体だけで十分です。

    例:

    select cup.cid, coalesce(cBudget.confvalue, upBudget.confvalue) as confvalue
    from @customertest as cup
    left join @conftest cBudget on (cBudget.cid = cup.cid and cBudget.confname = 'budget')
    left join @conftest upBudget on (upBudget.cid = cup.upid and upBudget.confname = 'budget')
    where cup.cid = 8;
    


    1. innondbエンジンを使用したmysqlデータベースへのPythonスクリプトからの挿入の問題

    2. MySQL#1140-GROUP列の混合

    3. utf8_general_ciで大文字と小文字を区別するmysql

    4. datetime2 の isdate() のような関数はありますか?