根据其他列中的值进行不同的分组依据

时间:2020-03-03 14:19:44

标签: sql sql-server group-by

我有两个桌子。 SalesData和AllOffers。

SalesData表具有品牌(不能为空),产品类型(不能为空),批次(不能为空),产品尺寸(不能为空),舞台(不能为空),省份(如果Stage =“ WIP”),包装日期(永远不能为null)和数量(永远不能为null),则为null。

AllOffers表具有Province(永远不能为空),要约编号(永远不能为空),产品类型(可以为空),品牌(永远不能为空),产品尺寸(永远不能为空),手数(永远不能为空),日期包装(永远不能为空),数量(永远不能为空)和商品状态(永远不能为空)。

我有一个包含两个窗格的应用程序。用户在左侧窗格中基于SalesData中可用的手创建“要约”,而右侧窗格显示具有附加“可用数量”列的SalesData表,该列是在用户创建要约时即时计算的。

数据需要按省,阶段,产品类型,尺寸和装箱日期进行分组,以提供可用数量。由于省份和产品类型为空,我无法对数据进行分组。

这就是我所拥有的

SELECT
        SalesData.Province,
        SalesData.Stage,
        SalesData.ProdType,
        SalesData.Brand, 
        SalesData.Size,
        SalesData.Lot,
        SalesData.PackedOn,
        SalesData.Qty, 
        CAST(SalesData.Qty AS decimal(12, 0)) - CAST(AllOffersSub.Qty AS decimal(12, 0)) AS Available 
    FROM
        SalesData LEFT OUTER JOIN 
        (
            SELECT
                    Province,
                    Brand,
                    Stage,
                    Lot,
                    Size,
                    PackedOn,
                    ProdType, 
                    SUM(CAST(Quantity AS decimal(12, 0))) AS Qty
                FROM
                    AllOffers
                WHERE
                    (OfferStatus = 'Unconfirmed')
                OR  (OfferStatus = 'Confirmed')
                GROUP BY
                    Province,
                    Brand,
                    Stage,
                    Lot,
                    Size,
                    PackedOn,
                    ProdType
        ) AS AllOffersSub ON
        AllOffersSub.Brand = SalesData.Brand
    AND AllOffersSub.Lot = SalesData.Lot
    AND AllOffersSub.Size = SalesData.Size
    AND AllOffersSub.PackedOn = SalesData.PackedOn
    AND AllOffersSub.Stage= SalesData.Stage
    AND CASE
            WHEN SalesData.Province IS NULL THEN 1 
            WHEN AllOfferssub.Province = SalesData.Province THEN 1 
            ELSE 0 END =1 
    AND CASE 
            WHEN SalesData.ProdType IS NULL AND AllOffersSub.ProdType IS NULL THEN 1 
            WHEN AllOfferssub.ProdType = SalesData.ProdType THEN 1  
            ELSE 0  
        END = 1;

问题在于,很多项目可以显示为WIP(进行中的工作,这意味着省份为空)和FG(制成品,这意味着省份不会为空)。对于这么多的订单,就不会进行分组,最后我得到了一个批次,并在日期,阶段,产品类型,尺寸上打包了相同的包装,显示的次数是与该批次有关的订单数的两倍。

有没有一种方法可以根据条件有选择地分组?例如,如果stage =“ WIP”,则按阶段,产品类型,尺寸和包装日期分组,否则按阶段,产品类型,尺寸和包装日期分组?

这是“优惠”表的示例:

ID|Customer|OfferNum|Stage|ProdType|Brand|Size|Lot|PackedOn|Quantity|Status
1 |A       | A1     |WIP  | Null   |test |Tst |aaa|1/1/2020|100     |Confirmed
2 |B       | B1     |WIP  | Null   |test |Tst |aaa|1/1/2020|100     |Unconfirmed
3 |C       | C1     |WIP  | Null   |test |Tst |aaa|1/1/2020|100     |Unconfirmed
4 |C       | C1     |FG   | Null   |test |Tst |aaa|1/1/2020|100     |Unconfirmed

这是SalesData表的示例:

ID|Brand|ProdType|Lot|Size|Stage|Customer|PackedOn|Qty
1 |test | Null   |aaa|Tst |WIP  |Null    |1/1/2020|1000
2 |test | Null   |aaa|Tst |FG   |C       |1/1/2020|1000

查询结果为:

Customer|Stage|ProdType|Brand|Size|Lot|PackedOn|Qty |Available
Null    |WIP  | Null   |test |Tst |aaa|1/1/2020|1000|900
Null    |WIP  | Null   |test |Tst |aaa|1/1/2020|1000|900
Null    |WIP  | Null   |test |Tst |aaa|1/1/2020|1000|900
C       |FG   | Null   |test |Tst |aaa|1/1/2020|1000|900

结果应为:

Customer|Stage|ProdType|Brand|Size|Lot|PackedOn|Qty |Available
Null    |WIP  | Null   |test |Tst |aaa|1/1/2020|1000|700
C       |FG   | Null   |test |Tst |aaa|1/1/2020|1000|900

1 个答案:

答案 0 :(得分:1)

我对您的查询进行了一些更改,但关键是您需要将子查询中的province更改为

iif(stage = 'wip', null, province)

为避免在select语句和group子句中重复代码,我将其放入名为ap的交叉应用语句中并从中选择。

除此之外,我只是将您的子查询放入公共表表达式中,将on子句中的case语句转换为or语句,然后重新设置样式。

with modifiedOffers as (

    select      ap.Province, 
                Brand, Stage, Lot, Size, PackedOn, ProdType, 
                Qty = sum(cast(Quantity as decimal(12, 0))) 
    from        @allOffers o
    cross apply (select Province = iif(stage = 'wip', null, province)) ap
    where       o.Status in ('Unconfirmed', 'Confirmed')
    group by    ap.Province, Brand, Stage, Lot, Size, PackedOn, ProdType

)

select      sd.Province, sd.Stage, sd.ProdType, sd.Brand, sd.Size, sd.Lot, sd.PackedOn, sd.Qty, 
            Available = CAST(sd.Qty AS decimal(12, 0)) - o.Qty 
from        @salesData sd
left join   modifiedOffers o  
                on o.Brand = sd.Brand
                and o.Lot = sd.Lot
                and o.Size = sd.Size
                and o.PackedOn = sd.PackedOn
                and o.Stage = sd.Stage
                and (o.Province = sd.Province or sd.Province is null)
                and (o.ProdType = sd.ProdType or sd.ProdType is null and o.ProdType is null);