【问题标题】:SQL Server Query - groupwise multiplicationSQL Server 查询 - 分组乘法
【发布时间】:2011-04-08 21:21:36
【问题描述】:

如果我们有这样的表:

Grp       Value

Grp1          2
Grp1          5
Grp1          3
Grp2          3
Grp2         -5
Grp2         -2
Grp3          4
Grp3          0
Grp3          1
Grp4         -2
Grp4         -4
Grp5          7
Grp5       NULL
Grp6       NULL
Grp6       NULL
Grp7         -1
Grp7        10

我们如何分组/乘以得到这个?

GrpID     Value

Grp1       30
Grp2       30
Grp3        0
Grp4        8
Grp5        7
Grp6     NULL
Grp7      -10

【问题讨论】:

    标签: sql-server tsql


    【解决方案1】:

    行值相乘与行值的对数相加

    诀窍是处理零和空值。

    好的,现在检查

    DECLARE @foo TABLE (GrpID varchar(10), Value float)
    
    INSERt @foo (GrpID, Value)
    SELECT 'Grp1',          2
    UNION ALL SELECT 'Grp1',          5
    UNION ALL SELECT 'Grp1',          3
    UNION ALL SELECT 'Grp2',          3
    UNION ALL SELECT 'Grp2',         -5
    UNION ALL SELECT 'Grp2',         -2
    UNION ALL SELECT 'Grp3',          4
    UNION ALL SELECT 'Grp3',          0
    UNION ALL SELECT 'Grp3',          1
    UNION ALL SELECT 'Grp4',         -2
    UNION ALL SELECT 'Grp4',         -4
    UNION ALL SELECT 'Grp5',          7
    UNION ALL SELECT 'Grp5',       NULL
    UNION ALL SELECT 'Grp6',       NULL
    UNION ALL SELECT 'Grp6',       NULL
    UNION ALL SELECT 'Grp7',         -1
    UNION ALL SELECT 'Grp7',        10 
    
    SELECT
        GrpID,
        CASE
           WHEN MinVal = 0 THEN 0
           WHEN Neg % 2 = 1 THEN -1 * EXP(ABSMult)
           ELSE EXP(ABSMult)
        END
    FROM
        (
        SELECT
           GrpID, 
           --log of +ve row values
           SUM(LOG(ABS(NULLIF(Value, 0)))) AS ABSMult,
           --count of -ve values. Even = +ve result.
           SUM(SIGN(CASE WHEN Value < 0 THEN 1 ELSE 0 END)) AS Neg,
           --anything * zero = zero
           MIN(ABS(Value)) AS MinVal
        FROM
           @foo
        GROUP BY
           GrpID
        ) foo
    

    【讨论】:

    • 为什么 CASE WHEN 值
    • @zvolkov:是的,应该。样本数据没有 >0 和
    【解决方案2】:

    在 SQL Server 中没有乘法/乘积聚合函数让我很恼火。 不幸的是,直到我已经以不同的方式解决了问题,我才找到上面给出的答案。我发布这个替代解决方案以防万一它可以帮助任何人,或者如果它被证明更有效。

    我的解决方案基本上涉及使用递归公用表表达式将所有值相乘。

    DECLARE @t TABLE (PID INT, ID INT, multiplier DECIMAL(14,5))
    
    INSERT @t
            (PID, ID, multiplier)
    VALUES  (1, 1, 1.5 )
          , (2, 1, 1.2)
          , (3, 2, 1.7)
          , (4, 3, 1)
          , (5, 4, 0.8)
          , (6, 4, 0.5)
          , (7, 4, 2)
          , (8, 4, 0.5)
    
    SELECT *, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY PID )
    FROM @t;
    
    
    WITH 
    trn AS
    (
    SELECT PID, ID, multiplier, ROW_NUMBER() OVER (PARTITION BY ID ORDER BY PID ) AS rn
    FROM @t
    ),
    tmu AS 
    (
        SELECT DISTINCT 
            ID, 
            trn.multiplier AS multiplier,
            1 AS Iteration
        FROM trn WHERE rn = 1
        UNION ALL 
        SELECT 
            trn.ID, CAST(tmu.multiplier * trn.multiplier AS DECIMAL(14,5)) AS multiplier
            , tmu.Iteration + 1 AS Iteration
        FROM
            tmu --AS tmu1
            JOIN trn ON tmu.ID = trn.ID AND tmu.Iteration + 1 = trn.rn 
    ),
    mxi AS
    (
        SELECT ID, COUNT(ID) AS Iter
        FROM trn
        GROUP BY ID
    )
    
    SELECT tmu.* 
    FROM tmu 
         JOIN mxi ON mxi.ID = tmu.ID AND mxi.Iter = tmu.Iteration
    ORDER BY ID
    

    起始表(+分区行号)选择到:

    PID ID  Multiplier  rn
    1   1   1.50000 1
    2   1   1.20000 2
    3   2   1.70000 1
    4   3   1.00000 1
    5   4   0.80000 1
    6   4   0.50000 2
    7   4   2.00000 3
    8   4   0.50000 4
    

    所有相乘的 ID / 乘数列表选择:

    ID  multiplier  Iteration
    1   1.80000 2
    2   1.70000 1
    3   1.00000 1
    4   0.40000 4
    

    【讨论】:

      【解决方案3】:

      这来自 CodePlex “聚合产品功能扩展 SQL”。我修改了语句以返回所需的结果,但 NULL 组除外,它返回“1”。

          SELECT GrpID, Exp(Sum(IIf(Abs(ISNULL(value,1))=0,0,Log(Abs(ISNULL(value,1))))))*IIf(Min(Abs(ISNULL(value,1)))=0,0,1)*
      (1-2*(Sum(IIf(ISNULL(value,1)>=0,0,1)) % 2)) AS value 
          FROM @foo
          GROUP BY GrpID;
      
      GrpID     Value
      
      Grp1       30
      Grp2       30
      Grp3        0
      Grp4        8
      Grp5        7
      Grp6        1
      Grp7      -10
      

      参考:http://productfunctionsql.codeplex.com/

      【讨论】:

        猜你喜欢
        • 2017-11-10
        • 2015-09-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-10-29
        • 2010-11-11
        相关资源
        最近更新 更多