【问题标题】:Using subselect in join to update table?在连接中使用子选择来更新表?
【发布时间】:2021-04-15 15:40:29
【问题描述】:

我正在尝试使用子选择更新具有列别名的表。问题是当我添加一个内部连接时,脚本会中断:

此更新有效,但子选择没有内部联接:

declare @erase table
(
id varchar(10),
total int
)
insert into @erase (id) select 'x'

declare @var1 int = 10
declare @var2 int = 10
declare @var3 int = 10
declare @var10 int = 10
declare @var11 int = 10
declare @var12 int = 10

update @erase 
set id = num / den
FROM
(
    select 
    'x' as id,
    @var1 * @var2 * @var3 * @var10* @var11* @var12 as 'num',
    @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as 'den'
) as innerTable

但是当我添加 join 时它会中断:

declare @erase table
(
id varchar(10),
total int
)
insert into @erase (id) select 'x'

declare @var1 int = 10
declare @var2 int = 10
declare @var3 int = 10
declare @var10 int = 10
declare @var11 int = 10
declare @var12 int = 10

update @erase 
set id = innerTable.num / innertable.den
from @erase inner join innertable on
@erase.id = innertable.id
FROM
(
    select 
    'x' as id,
    @var1 * @var2 * @var3 * @var10* @var11* @var12 as 'num',
    @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as 'den'
) as innerTable

我想使用cte,但我需要一个额外的num / den 存储库。以下将不起作用:

;with cte as
(
    select 
    'x' as id,
    @var1 * @var2 * @var3 * @var10* @var11* @var12 as 'num',
    @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as 'den',
    num / den as 'total' -- will break
)
update @erase 
set total = cte.total
from @erase inner join cte on
@erase.id = cte.id

如何在生成num / den 的同一事务中更新@erase?

编辑: 我找到了解决方法,但我仍然无法使用最终值“总计”进行更新:

;with cte as
(
    select 
    'x' as id,
    @var1 * @var2 * @var3 * @var10* @var11* @var12 as 'num',
    @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as 'den',
    num / den as 'total' -- will break
)
update @erase 
set total = num / den --Although I prefer using alias total.
from @erase inner join cte on
@erase.id = cte.id

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    首先,这个示例:

    update @erase 
    set id = innerTable.num / innertable.den
    from @erase inner join innertable on
    @erase.id = innertable.id
    FROM
    (
        select 
        'x' as id,
        @var1 * @var2 * @var3 * @var10* @var11* @var12 as 'num',
        @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as 'den'
    ) as innerTable
    

    这里的问题是有两个 FROM 子句。你可以通过指定innertable inline 来修复它,如下所示:

    update @erase 
    set id = innerTable.num / innertable.den
    from @erase 
    inner join (
        select 
        'x' as id,
        @var1 * @var2 * @var3 * @var10* @var11* @var12 as num,
        @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as den
    ) innertable on @erase.id = innertable.id
    

    然后是 CTE 版本:

    with cte as
    (
        select 
        'x' as id,
        @var1 * @var2 * @var3 * @var10* @var11* @var12 as 'num',
        @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as 'den',
        num / den as 'total' -- will break
    )
    

    这里的问题是total 行上的num 和den 尚不作为可用名称存在。您可以通过多种方式解决此问题,但一种选择是在多个 CTE 中分层查询:

    with cte1 as
    (
        select 
        'x' as id,
        @var1 * @var2 * @var3 * @var10* @var11* @var12 as num,
        @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as den,
    ), 
    cte2 As (
        select *,  num/den as total from cte1
    )
    update @erase 
    set total = cte2.total
    from @erase 
    inner join cte2 on @erase.id = cte2.id
    

    另一种选择是重复表达式:

    with cte as
    (
        select 
        'x' as id,
        @var1 * @var2 * @var3 * @var10* @var11* @var12 as num,
        @var1 + @var2 + @var3 + @var10+ @var11+ @var12 as den,
        ( @var1 * @var2 * @var3 * @var10* @var11* @var12 )
          / 
        ( @var1 + @var2 + @var3 + @var10+ @var11+ @var12 ) as total
    )
    update @erase 
    set total = cte.total
    from @erase 
    inner join cte on @erase.id = cte.id
    

    【讨论】:

    • 非常感谢。
    猜你喜欢
    • 2015-12-25
    • 2019-12-06
    • 1970-01-01
    • 2014-04-08
    • 1970-01-01
    • 1970-01-01
    • 2020-08-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多