我有一个包含列的表 - id,x1,x2,x3,x4
如果我有值
1,y,y,y,y
2,y,null,n,null
3,y,null,null,null
然后说,我想计算(1)/(y的数量) 并将行显示为
1,.25,.25,.25,.25
2,1,0,0,0
3,1,0,0,0
是否可以使用sql查询执行此操作?
答案 0 :(得分:1)
这里的天真版本将是
SELECT
id,
CASE
WHEN x1 IS NULL THEN
0
WHEN f_eval(x1) + f_eval(x2,0) + f_eval(x3,0) + f_eval(x4,0) = 0 THEN
-- default value
ELSE
1 / (f_eval(x1) + f_eval(x2,0) + f_eval(x3,0) + f_eval(x4,0))
END,
-- repeat for each column
FROM
Table
其中f_eval被定义为或多或少以下:
CREATE FUNCTION f_eval(
@x_value varchar(1)
BEGIN
DECLARE @return_val int
SELECT
@return_val =
case
WHEN ISNULL(@x_value, 'n') = 'y' THEN
1
ELSE
0
END
RETURN @return_val
END
答案 1 :(得分:1)
试试foillowing
select
(SUM(case when x1 is null then 0 else 1 end))* 1.0/ ((SUM(case when x1 is null then 0 else 1 end) + SUM(case when x2 is null then 0 else 1 end)+ SUM(case when x3 is null then 0 else 1 end) + + SUM(case when x4 is null then 0 else 1 end)) * 1.0),
(SUM(case when x2 is null then 0 else 1 end))* 1.0/ ((SUM(case when x1 is null then 0 else 1 end) + SUM(case when x2 is null then 0 else 1 end)+ SUM(case when x3 is null then 0 else 1 end) + + SUM(case when x4 is null then 0 else 1 end)) * 1.0),
(SUM(case when x3 is null then 0 else 1 end))* 1.0/ ((SUM(case when x1 is null then 0 else 1 end) + SUM(case when x2 is null then 0 else 1 end)+ SUM(case when x3 is null then 0 else 1 end) + + SUM(case when x4 is null then 0 else 1 end)) * 1.0),
(SUM(case when x4 is null then 0 else 1 end))* 1.0/ ((SUM(case when x1 is null then 0 else 1 end) + SUM(case when x2 is null then 0 else 1 end)+ SUM(case when x3 is null then 0 else 1 end) + + SUM(case when x4 is null then 0 else 1 end)) * 1.0)
from table group by id
您可能确保不要除以零
编辑2
通过在0和1之后向分母添加一个案例。 你也应该改变
case when x1 is null then 0 else 1 end
到
case when x1 = 'y' then 1 else 0 end
答案 2 :(得分:1)
这是使用子查询的另一种暴力攻击。设置一些测试数据:
CREATE TABLE MyTable
(
Id int not null
,Col1 char(1) null
,Col2 char(1) null
,Col3 char(1) null
,Col4 char(1) null
)
INSERT MyTable
select 1, 'Y', 'Y', 'Y', 'Y'
union all select 2, 'Y', null, 'N', null
union all select 3, 'Y', null, null, null
union all select 4, null, null, null, null
我使用了字符数据作为目标值,但你应该没有问题使它成为数字。我添加了第四行来检查除零(感谢ps!)。所以,
SELECT
mt.ID
,case mt.Col1 when 'Y' then xx.distrib else 0 end
,case mt.Col2 when 'Y' then xx.distrib else 0 end
,case mt.Col3 when 'Y' then xx.distrib else 0 end
,case mt.Col4 when 'Y' then xx.distrib else 0 end
from MyTable mt
inner join (select
ID
,1.0 / ( case Col1 when 'Y' then 1 else 0 end
+ case Col2 when 'Y' then 1 else 0 end
+ case Col3 when 'Y' then 1 else 0 end
+ case Col4 when 'Y' then 1 else 0 end) distrib
from MyTable) xx
on xx.Id = mt.Id
似乎产生了预期的结果。 (单独运行子查询,你得到零除......但老实说我不知道为什么运行整个查询不会。
答案 3 :(得分:1)
试试这个
示例数据
declare @t table( Id int,Col1 char(1) null,Col2 char(1) null,Col3 char(1) null,Col4 char(1) null)
INSERT @t select 1, 'Y', 'Y', 'Y', 'Y' union all select 2, 'Y', null, null, null
union all select 3, 'Y', null, null, null
<强>查询:强>
select t.id
,case Col1 when 'Y' then LEFT(cast( 1.0/x.cntys as varchar(20)),4) else cast( 0 as varchar(1)) end x1
,case Col2 when 'Y' then LEFT(cast( 1.0/x.cntys as varchar(20)),4) else cast( 0 as varchar(1)) end x2
,case Col3 when 'Y' then LEFT(cast( 1.0/x.cntys as varchar(20)),4) else cast( 0 as varchar(1)) end x3
,case Col4 when 'Y' then LEFT(cast( 1.0/x.cntys as varchar(20)),4) else cast( 0 as varchar(1)) end x4
from @t t
join(
select ROW_NUMBER() over(order by getdate()) rn,
COUNT(col1) + COUNT(col2) + COUNT(col3) + COUNT(col4) cntys from @t
group by id)X
on t.Id = X.rn
<强>输出:强>
id x1 x2 x3 x4
1 0.25 0.25 0.25 0.25
2 1.00 0 0 0
3 1.00 0 0 0