【问题标题】:When to use the table operator APPLY何时使用表运算符 APPLY
【发布时间】:2013-08-10 05:03:01
【问题描述】:

我正在尝试理解表运算符APPLY

示例如下:

CREATE TABLE #y ( Name char(8), hoursWorked int);
GO
INSERT INTO #y VALUES ('jim',4);
INSERT INTO #y VALUES ('michael',40);
INSERT INTO #y VALUES ('raj',1000);
INSERT INTO #y VALUES ('jason',7);
INSERT INTO #y VALUES ('tim',50);
GO

CREATE TABLE #x ( Name char(8),game char(8), NumBets int);
GO
INSERT INTO #x VALUES ('jim','chess',4);
INSERT INTO #x VALUES ('jim','BG',10);
INSERT INTO #x VALUES ('jim','draughts',100);
INSERT INTO #x VALUES ('jim','football',5);
INSERT INTO #x VALUES ('michael','chess',40);
INSERT INTO #x VALUES ('michael','BG',7);
INSERT INTO #x VALUES ('michael','draughts',65);
INSERT INTO #x VALUES ('michael','football',50);
INSERT INTO #x VALUES ('raj','chess',400);
INSERT INTO #x VALUES ('raj','BG',70);
INSERT INTO #x VALUES ('raj','draughts',650);
INSERT INTO #x VALUES ('tim','draughts',60000);
GO

SELECT  y.Name, 
        y.hoursWorked,
        x.game,
        x.NumBets
FROM    #y y
        OUTER APPLY 
          (
          SELECT TOP 2 *
          FROM   #x
          WHERE  Name = y.Name 
          ORDER BY NumBets
        ) x
ORDER BY  y.Name,
        x.NumBets DESC;

我的主要障碍是理解何时使用APPLY
所以我想知道使用在sql-server 2005 中实现的standard sql 获得与上述相同的结果有多困难?
APPLY 是否使查询更短或更易读?
如果这个例子没有显示使用APPLY 的巨大优势,那么使用APPLY 有优势的明显例子是什么?

【问题讨论】:

    标签: sql sql-server sql-server-2012 cross-apply sql-standards


    【解决方案1】:

    首先 - 使用apply,您可以调用表值函数,其中参数值取自您查询的表,如下所示:

    select
        t1.col3, -- column from table
        f1.col1  -- column from function
    from table1 as t1
        left outer join table2 as t2 on t2.col1 = t1.col1
        outer apply dbo.function1(t1.col1, t2.col2) as f1
    

    粉碎 xml 列

    select
        t1.col3,
        t.c.value('@value', 'int') as value
    from table1 as t1
        -- table1.col1 is xml iike <Data @Value="...">...</Data>
        outer apply t1.col1.nodes('Data') as t(c) 
    

    根据我的经验,apply 在您必须进行一些预先计算时非常有用:

    select
        t1.col3,
        a1.col1,  --calculated value
        a2.col1   -- another calculated value, first one was used
    from table1 as t1
        outer apply (select t1.col1 * 5 as col1) as a1
        outer apply (select a1.col1 - 4 as col1) as a2
    

    另一个使用apply的例子是unpivot操作:

    select
        t1.col1, c.name, c.value
    from table1 as t1
        outer apply (
            select 'col1', t1.col1 union all
            select 'col2', t1.col2
        ) as c(name, value)
    

    最后,这里是您的查询在没有使用 apply 的情况下根据 SQL 2005 实现的:

    ;with cte as (
        select
            y.Name, 
            y.hoursWorked,
            x.game,
            x.NumBets,
            row_number() over(partition by x.Name order by x.NumBets) as row_num
        from y
            left outer join x on x.Name = y.Name
    )
    select Name, hoursWorked, game, NumBets
    from cte
    where row_num <= 2
    order by Name, NumBets desc
    

    参见sql fiddle 示例

    【讨论】:

    • +1 非常好的广泛答案 - 还没有时间完全吸收这个
    • 我认为APPLY 比 2005 版本短。不太确定我是否曾经使用过UNPIVOT 版本——这是一个不错的技巧,但由于特定的UNPIVOT 函数随同版本的sql-server 一起提供,为什么不直接使用它。对我来说,最好的应用似乎是它与 TVF 的交互,以及 apply 用于计算的相关使用。
    • 我觉得 Apply 可能比 row_number 快,但不确定这个,得稍后测试
    猜你喜欢
    • 2012-12-13
    • 2022-01-12
    • 2011-05-30
    • 2021-11-11
    • 1970-01-01
    • 2010-12-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多