SQL Query根据值/ null计算权重或分配权重

时间:2009-12-17 16:08:14

标签: .net sql-server sql-server-2005 tsql stored-procedures

我有一个包含列的表 - 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查询执行此操作?

4 个答案:

答案 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 
相关问题