我有一个具有单行和两列的表。我可以使用SQL查询从行中获取最小值吗?
value1 value2
1 43 39
查询应返回值39。
最简单的方法可能是apply
:
select t.*, v.min_val
from t cross apply
(select min(val) as min_val
from (values (value1), (value2)) v(val)
) v;
对于仅两个非空值,您case
表达式也很简单:
select t.*,
(case when value1 < value2 then value1 else value2 end) as min_val
from t;
但是,这不会忽略null
值。而且它不像人们想要的那样容易地推广。
当然Gordon's答案(+1)表现更好,将是我的首选,但是如果偶然您正在寻找一个更“通用”的版本,这是一个表值函数
示例
Declare @YourTable table (ID int,EEE money,EESI money,EETPL money,AA varchar(25),somedate date)
Insert into @YourTable values
(1,10,20.5,30,'aa','2017-05-01'),
(2,40,50,60,'bb','2017-05-10')
Select A.ID
,B.*
From @YourTable A
Cross Apply [dbo].[tvf-Stat-Row-Agg]('ID,OtherCols,ToExclude',(Select A.* For XML RAW) ) B
返回
ID RetCnt RetSum RetMin RetMax RetAvg RetStd
1 3 60.5 10 30 20.1666666666667 10.0041657989726
2 3 150 40 60 50 10
TVF,如果有兴趣
CREATE FUNCTION [dbo].[tvf-Stat-Row-Agg](@Exclude varchar(500),@XML xml)
Returns Table
As
Return (
Select RetCnt = count(value)
,RetSum = Sum(Value)
,RetMin = Min(Value)
,RetMax = Max(Value)
,RetAvg = Avg(Value)
,RetStd = Stdev(Value)
From (
Select Item = xAttr.value('local-name(.)','varchar(100)')
,Value = try_convert(float,xAttr.value('.','varchar(max)'))
From @XML.nodes('//@*') x(xAttr)
) S
Where charindex(','+S.Item+',',','+@Exclude+',')=0
);
注意:如果使用2016 +,JSON可能会提高性能。
Select A.ID
,B.*
from @YourTable A
Cross Apply [dbo].[tvf-Stat-Row-Agg-JSON]('ID',(Select A.* For JSON Path,Without_Array_Wrapper ) ) B
CREATE FUNCTION [dbo].[tvf-Stat-Row-Agg-JSON](@Exclude varchar(500),@json varchar(max))
Returns Table
As Return (
Select RetCnt = count(value)
,RetSum = Sum(Value)
,RetMin = Min(Value)
,RetMax = Max(Value)
,RetAvg = Avg(Value)
,RetStd = Stdev(Value)
From ( Select [Key],Value=try_convert(float,Value) From OpenJson(@json) ) A
Where charindex(','+[Key]+',',','+@Exclude+',')=0
)