是否可以从这个标量函数中创建一个内联 Table 值函数?
Is it Possible to Create an Inline Table-valued Function out of this Scalar Function?
我很确定答案是否定的,但我想仔细检查一下。如果有办法,您实际上不必对其进行编码,对方法的建议可能会有所帮助。我已经尝试了 1 个大的 Select 和子查询等,但我不知道如何让它选择正确的记录。
table 必须重新加入自身以获得反向关系。下面的代码只是一个测试示例。
谢谢
create function [dbo].[fnUOMFactor_Inline] (
@ItemID nvarchar(20)
, @FromUnit nvarchar(10)
, @ToUnit nvarchar(10)
)
returns numeric(28,12)
as
begin
declare @Factor numeric(28,12)
if @FromUnit = @ToUnit
set @Factor = 1
-- Simple 1-step
if @Factor is null
select @Factor = factor
from dbo.UnitConvertTest
WHere itemid = @ItemID
and fromunit = @FromUnit
and tounit = @ToUnit
-- Inverted 1-step
if @Factor is null
select @Factor = 1/factor
from dbo.UnitConvertTest
Where itemid = @ItemID
and fromunit = @ToUnit
and tounit = @FromUnit
if @Factor is null
select @Factor = uc1.factor * uc2.factor
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.tounit = uc2.fromunit
where uc1.itemid = @ItemID
and uc1.fromunit = @FromUnit
and uc2.tounit = @ToUnit
and uc1.factor <> 0
and uc2.factor <> 0
-- Inverted 2-step
if @Factor is null
select @Factor = 1 / (uc1.factor * uc2.factor)
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.tounit = uc2.fromunit
Where uc1.itemid = @ItemID
and uc1.fromunit = @ToUnit
and uc2.tounit = @FromUnit
-- Complex 2-step (same fromunit)
if @Factor is null
select @Factor = uc1.factor / uc2.factor
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.fromunit = uc2.fromunit
Where uc1.itemid = @ItemID
and uc1.tounit = @ToUnit
and uc2.tounit = @FromUnit
-- Complex 2-step (same tounit)
if @Factor is null
select @Factor = uc1.factor / uc2.factor
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.tounit = uc2.tounit
Where uc1.itemid = @ItemID
and uc1.fromunit = @FromUnit
and uc2.fromunit = @ToUnit
-- Default
if @Factor is null
set @Factor = 1
return @Factor
end
这是一个table,有一些测试记录。
CREATE TABLE [dbo].[UnitConvertTest](
[FROMUNIT] [nvarchar](10) NOT NULL,
[TOUNIT] [nvarchar](10) NOT NULL,
[FACTOR] [numeric](28,12) NOT NULL,
[ITEMID] [nvarchar](20) NOT NULL,
) ON [PRIMARY]
insert into dbo.UnitConvertTest (FROMUNIT, TOUNIT, FACTOR, ITEMID)
Values ('CT','PT','40.00','TEST')
, ('RM','CT','10.00','TEST')
, ('RM','PT','400.00','TEST')
Select [dbo].[fnUOMFactor_Inline] ('Test','PT','RM')
任何无循环标量函数都可以通过机械转换变成内联 TVP。不过,转换可能会导致大查询。
您的代码似乎是一连串回退计算。你可以这样写:
select FinalResult = coalesce(x.factor, f1.fallback, f2.fallback, f3.fallback, ...)
from (values (convert(decimal(28, 12, null))) x(factor)
cross apply (select fallback = {computeFallback1}) f1
cross apply (select fallback = {computeFallback2}) f2
cross apply (select fallback = {computeFallback3}) f3
...
本质上,这通过一行 table 对一系列标量计算进行建模,我们不断向其中添加列...
这可能会导致查询出现性能问题。它可能会强制循环连接。
我很确定答案是否定的,但我想仔细检查一下。如果有办法,您实际上不必对其进行编码,对方法的建议可能会有所帮助。我已经尝试了 1 个大的 Select 和子查询等,但我不知道如何让它选择正确的记录。
table 必须重新加入自身以获得反向关系。下面的代码只是一个测试示例。
谢谢
create function [dbo].[fnUOMFactor_Inline] (
@ItemID nvarchar(20)
, @FromUnit nvarchar(10)
, @ToUnit nvarchar(10)
)
returns numeric(28,12)
as
begin
declare @Factor numeric(28,12)
if @FromUnit = @ToUnit
set @Factor = 1
-- Simple 1-step
if @Factor is null
select @Factor = factor
from dbo.UnitConvertTest
WHere itemid = @ItemID
and fromunit = @FromUnit
and tounit = @ToUnit
-- Inverted 1-step
if @Factor is null
select @Factor = 1/factor
from dbo.UnitConvertTest
Where itemid = @ItemID
and fromunit = @ToUnit
and tounit = @FromUnit
if @Factor is null
select @Factor = uc1.factor * uc2.factor
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.tounit = uc2.fromunit
where uc1.itemid = @ItemID
and uc1.fromunit = @FromUnit
and uc2.tounit = @ToUnit
and uc1.factor <> 0
and uc2.factor <> 0
-- Inverted 2-step
if @Factor is null
select @Factor = 1 / (uc1.factor * uc2.factor)
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.tounit = uc2.fromunit
Where uc1.itemid = @ItemID
and uc1.fromunit = @ToUnit
and uc2.tounit = @FromUnit
-- Complex 2-step (same fromunit)
if @Factor is null
select @Factor = uc1.factor / uc2.factor
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.fromunit = uc2.fromunit
Where uc1.itemid = @ItemID
and uc1.tounit = @ToUnit
and uc2.tounit = @FromUnit
-- Complex 2-step (same tounit)
if @Factor is null
select @Factor = uc1.factor / uc2.factor
from dbo.UnitConvertTest uc1
join dbo.UnitConvertTest uc2 on uc1.itemid = uc2.itemid
and uc1.tounit = uc2.tounit
Where uc1.itemid = @ItemID
and uc1.fromunit = @FromUnit
and uc2.fromunit = @ToUnit
-- Default
if @Factor is null
set @Factor = 1
return @Factor
end
这是一个table,有一些测试记录。
CREATE TABLE [dbo].[UnitConvertTest](
[FROMUNIT] [nvarchar](10) NOT NULL,
[TOUNIT] [nvarchar](10) NOT NULL,
[FACTOR] [numeric](28,12) NOT NULL,
[ITEMID] [nvarchar](20) NOT NULL,
) ON [PRIMARY]
insert into dbo.UnitConvertTest (FROMUNIT, TOUNIT, FACTOR, ITEMID)
Values ('CT','PT','40.00','TEST')
, ('RM','CT','10.00','TEST')
, ('RM','PT','400.00','TEST')
Select [dbo].[fnUOMFactor_Inline] ('Test','PT','RM')
任何无循环标量函数都可以通过机械转换变成内联 TVP。不过,转换可能会导致大查询。
您的代码似乎是一连串回退计算。你可以这样写:
select FinalResult = coalesce(x.factor, f1.fallback, f2.fallback, f3.fallback, ...)
from (values (convert(decimal(28, 12, null))) x(factor)
cross apply (select fallback = {computeFallback1}) f1
cross apply (select fallback = {computeFallback2}) f2
cross apply (select fallback = {computeFallback3}) f3
...
本质上,这通过一行 table 对一系列标量计算进行建模,我们不断向其中添加列...
这可能会导致查询出现性能问题。它可能会强制循环连接。