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

1つの選択列の値を保存して、次の列に使用することは可能ですか?

    CROSS APPLYが必要です ここでは、外部参照を参照でき、煩わしいサブクエリやCTEは必要ありません:

    select col1, col2
    from table1 as outer_table
    
    -- can also have multi-row values
    cross apply (values (complex_expression_1) ) as v1 (col1)
    cross apply (values (expression_referring_to_col1) ) as v2 (col2)
    
    -- alternate syntax, select without from returns a single row
    cross apply (select complex_expression_1 as col1 ) AS v1
    cross apply (select expression_referring_to_col1 as col2 ) as v2
    
    -- you can also do anything you like in there, can be one or multiple rows
    cross apply (
        select complex_expression_1 as col1 
        from othercomplexjoin as o
        where o.join_column = outer_table.join_column
    ) AS v1
    

    APPLYでできるいくつかのトリック :

    1。子テーブルのグループごとのトップ1:

    「グループごとのトップ1」の古典的な解決策は、row_number()を使用することです。 。これにより、特に子テーブルに比べて個別の外部値の数が少ない場合に、大量のスキャンが発生する可能性があります。

    select
        o.id,
        lastPayment.Date
    from order_header as o
    join
    ( select *, row_number() over (partition by order_id order by date desc) as rn
     from payments
    ) as lastPayment on ...
    where lastPayment.rn = 1
    

    代わりに次のことができます:

    select
        o.id,
        lastPayment.Date
    from order_header as o
    cross apply
    ( select top (1) *
     from payments as p
     where p.order_id = o.id
     order by date desc
    ) as lastPayment
    

    注:OUTER APPLY 概念的には左結合を置き換えます。つまり、行がない代わりにnullを返します。

    2。ピボット解除

    select
        o.id,
        customer.*
    from order_header as o
    cross apply ( values    -- This returns two rows for every order_header
        ( 'DeliveryCustomer', o.deliveryCustomer ),
        ( 'billingCustomer', o.billingCustomer )
    ) as customer (type, name)
    

    3。行を可変回数で展開する:

    ある金額を取得して、それを別の行に分割するとします。 amount <= 50の場合 次に、1行のamount> 50の場合 次に、50行と残りの行の2行:

    select t.id, v.amount
    from table as t
    cross apply (
        select case when amount > 50 then 50 else amount end as amount
        union all
        select amount - 50   -- note this row will not appear if amount < 50
        where amount > 50
    ) v
    


    1. MySQLとMariaDB:知っておくべきこと

    2. プライマリインデックスとセカンダリインデックスの正確な違いは何ですか?

    3. ラッチの概要

    4. SQLで3つのテーブルを結合する