产品组合为单一计数

时间:2016-05-12 13:01:39

标签: sql sql-server-2008 reporting-services

我需要将事务中的产品组合与其他产品区分开来,并且我正在努力解决如何在SQL 2008的单个select语句中执行此操作。这将成为在Reporting Services中操作的数据集

原始数据看起来像这样

txn, prod, units  
1,    a,    2  
1,    c,    1  
2,    a,    1  
2,    b,    1  
2,    c,    1  
3,    a,    2  
3,    b,    1  
4,    a,    3  
4,    c,    2

因此,如果在相同的反转数中,a + b应该= 1,但是如果不配对,则a或b应该等于1。所以a = 1和b = 1但a + b = 1,a + b + a = 2,a + b + a + b = 2这里给出的示例数据是我想要的结果,并解释为什么

txn 1 is 3 units -- 2a + c  
txn 2 is 2 units -- (a+b) + c  
txn 3 is 2 units -- (a+b) + a  
txn 4 is 5 units -- 3a + 2c

我的查询比这更复杂,并包含其他聚合,所以我想按事务分组,我不能这样做,因为我需要操作较低的粒度

更新进度:

可能的解决方案,我根据我正在测量的产品生成了列。这允许我在Txn上分组,因为我现在正在聚合该字段。不确定是否有更好的方法,因为它需要一点时间

CASE    WHEN    SUM(CASE    WHEN Prod='a' then 1 else 0 end)-
                SUM(CASE    WHEN Prod='b' then 1 else 0 end)=0 
        THEN    SUM(CASE    WHEN Prod='a' then 1 else 0 end) 
        ELSE 0 END AS MixProd
, CASE  WHEN    SUM(CASE    WHEN Prod='a' then 1 else 0 end)-
                SUM(CASE    WHEN Prod='b' then 1 else 0 end)!=0 
        THEN    ABS(SUM(CASE    WHEN Prod='a' then 1 else 0 end)-
                    SUM(CASE    WHEN Prod='b' then 1 else 0 end)) 
        ELSE 0 END AS NotMixProd

然后我需要整理当前单位聚合以删除附加内容但这肯定会让我有个开始

更新进度2:

如果a或b为0,则无法正确处理0,它仍会为mix提供值,因为a-b不为零。我恢复了早先的草案,我丢失并扩展如下

, CASE          WHEN        SUM(CASE    WHEN Prod='a' then 1 else 0 end) = 0 THEN 0 
                WHEN        SUM(CASE    WHEN Prod='b' then 1 else 0 end) = 0 THEN 0
                WHEN        SUM(CASE    WHEN Prod='a' then 1 else 0 end)-
                            SUM(CASE    WHEN Prod='b' then 1 else 0 end)=0 
                THEN        SUM(CASE    WHEN Prod='a' then 1 else 0 end) 
                ELSE        ABS(SUM(CASE    WHEN Prod='a' then 1 else 0 end)-
                            SUM(CASE    WHEN Prod='b' then 1 else 0 end))       
                END AS MixProd
        , CASE  WHEN        SUM(CASE    WHEN Prod='a' then 1 else 0 end)-
                            SUM(CASE    WHEN Prod='b' then 1 else 0 end)!=0 
                THEN        ABS(SUM(CASE    WHEN Prod='a' then 1 else 0 end)-
                            SUM(CASE    WHEN Prod='b' then 1 else 0 end)) 
                ELSE 0      END AS NotMixProd

2 个答案:

答案 0 :(得分:0)

更新:这应该适用于SQL Server 2008(基于here的LAG解决方案)。

以下是演示:http://rextester.com/GNI23706

WITH CTE AS
(
    select txn, prod, units,
     row_number() over (partition by txn order by prod) rn,
    (row_number() over (partition by txn order by prod))/2 rndiv2,
    (row_number() over (partition by txn order by prod)+1)/2 rnplus1div2,
    count(*) over (partition by txn) partitioncount
    from test_data
)

select 
txn,
sum(case when prev_prod = 'a' and prod = 'b' and prev_units >= units then 0
         when prev_prod = 'a' and prod = 'b' and prev_units < units then units - prev_units
         else units
    end) units
from
(
    select 
    txn,
    prod,
    units,
    CASE WHEN rn%2=1 
         THEN MAX(CASE WHEN rn%2=0 THEN prod END) OVER (PARTITION BY txn,rndiv2) 
         ELSE MAX(CASE WHEN rn%2=1 THEN prod END) OVER (PARTITION BY txn,rnplus1div2)
    END AS prev_prod,
    CASE WHEN rn%2=1 
         THEN MAX(CASE WHEN rn%2=0 THEN units END) OVER (PARTITION BY txn,rndiv2) 
         ELSE MAX(CASE WHEN rn%2=1 THEN units END) OVER (PARTITION BY txn,rnplus1div2)
    END AS prev_units
    from cte
) temp
group by txn

对于SQL Server 2012+,请使用LAG:

select 
txn,
sum(
case when prev_prod = 'a' and prod = 'b' and prev_units >= units then 0
     when prev_prod = 'a' and prod = 'b' and prev_units < units then units - prev_units
     else units
end) units
from
(
    select 
    txn,
    prod,
    units,
    lag(prod) over (partition by txn order by prod) prev_prod,
    lag(units) over (partition by txn order by prod) prev_units
    from test_data
) temp
group by txn

答案 1 :(得分:0)

我最终决定临时表是最好的方法,因为我无法对整理进行分组。所以我最终调整了上面的代码,因为它没有正确地拿起备用物品

SUM(Units) AS OldUnits
SUM(Units) - 
    (CASE WHEN 
 SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) = 0 THEN 0 WHEN 
 SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END) = 0 THEN 0 WHEN 
 SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) - 
 SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END) = 0 THEN 
 SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) WHEN 
(SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) - 
 SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END)) < 0 THEN 
 SUM(CASE WHEN Prod='a' THEN 1 ELSE 0 END) ELSE 
 SUM(CASE WHEN Prod='b' THEN 1 ELSE 0 END) END) AS NewUnits

这被存储在一个temptable中,然后我可以在Trans上进行整理,作为下一步。为我的目的工作正常,并帮助我克服了我对temptables的温和的非理性恐惧