以物品计数&前两个月的频道已售出

时间:2016-08-21 19:56:07

标签: sql tsql sql-server-2016

跟进我的上一个问题,Counting Items based on First Month Sold,我需要在销售的前两个月内计算物品,但也需要按渠道分组以及物品,以及销售的总物品数量。

参见下面的示例代码

DECLARE @sales table(
itemnumber int,
saledate date,
channeltype varchar,
ordid varchar, 
orditemqty int)

INSERT INTO @sales VALUES(43029, '2011-26-03', Channel2, 1, 5)
INSERT INTO @sales VALUES(43029, '2011-26-03', Channel2, 2, 6)
INSERT INTO @sales VALUES(43029, '2011-26-03', Channel2, 3, 2)
INSERT INTO @sales VALUES(43029, '2011-26-03', Channel2, 4, 3)
INSERT INTO @sales VALUES(43029, '2011-26-03', Channel2, 4, 1)
INSERT INTO @sales VALUES(43029, '2011-26-04', Channel2, 5, 5)
INSERT INTO @sales VALUES(43029, '2011-26-04', Channel2, 5, 7)
INSERT INTO @sales VALUES(43030, '2011-26-04', Channel1, 5, 8)
INSERT INTO @sales VALUES(43030, '2011-26-04', Channel2, 6, 1)
INSERT INTO @sales VALUES(43030, '2011-26-04', Channel1, 7, 2)
INSERT INTO @sales VALUES(43030, '2011-26-04', Channel2, 8, 4)
INSERT INTO @sales VALUES(43030, '2011-26-04', Channel2, 8, 6)
INSERT INTO @sales VALUES(43030, '2011-26-04', Channel2, 8, 1)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 9, 8)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 9, 9)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 9, 10)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 9, 11)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 9, 1)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 9, 4)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel2, 19, 7)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel2, 19, 9)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 25, 10)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 25, 11)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel1, 25, 10)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel2, 27, 1)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel2, 27, 4)
INSERT INTO @sales VALUES(43030, '2011-26-05', Channel2, 27, 6)
INSERT INTO @sales VALUES(43050, '2011-26-05', Channel1, 28, 8)
INSERT INTO @sales VALUES(43050, '2011-26-05', Channel2, 29, 9)
INSERT INTO @sales VALUES(43050, '2011-26-05', Channel1, 39, 1)
INSERT INTO @sales VALUES(43050, '2011-26-05', Channel2, 30, 4)
INSERT INTO @sales VALUES(43050, '2011-26-06', Channel1, 31, 9)
INSERT INTO @sales VALUES(43050, '2011-26-06', Channel1, 31, 1)
INSERT INTO @sales VALUES(43050, '2011-26-07', Channel1, 45, 6)
INSERT INTO @sales VALUES(43090, '2011-26-07', Channel2, 61, 3)
INSERT INTO @sales VALUES(43090, '2011-26-07', Channel2, 61, 4)
INSERT INTO @sales VALUES(43090, '2011-26-07', Channel2, 61, 5)
INSERT INTO @sales VALUES(43090, '2011-26-07', Channel2, 61, 8)
INSERT INTO @sales VALUES(43090, '2011-26-08', Channel1, 71, 2)
INSERT INTO @sales VALUES(43090, '2011-26-08', Channel1, 71, 3)
INSERT INTO @sales VALUES(43090, '2011-26-09', Channel1, 76, 5)

输出如下所示

ITEMNO| CHANNELTYPE | YEARMONTH | COUNT | QTY
---------------------------------------------
43029 | Channel1    | 03-2011   | 0     | 0
43029 | Channel2    | 03-2011   | 7     | 29
43030 | Channel1    | 04-2011   | 11    | 84
43030 | Channel2    | 04-2011   | 9     | 39
43050 | Channel1    | 05-2011   | 4     | 19
43050 | Channel2    | 05-2011   | 2     | 13 
43090 | Channel1    | 07-2011   | 2     | 5
43090 | Channel2    | 07-2011   | 4     | 20

只有在第一次订购商品的前两个月内出售时才会出现计数,其中可能是多个渠道之一(我使用的是Channel1,而2则是示例,但可能有几个)但是总是有一个频道。我想要显示所有频道并显示0的数量,如果没有任何东西,那么在这种情况下数量也是0(例如,在第一个频道中在一个频道中销售的项目)两个月但不是第二个频道)。

谢谢!

3 个答案:

答案 0 :(得分:2)

这看起来有点棘手。一种方法是使用cross join生成所需的所有行,然后使用left join引入计数:

with icym as (
      select s.item_id, s.channel,
             format(saledate, 'yyyy-mm') as yyyymm,
             count(*) as cnt
      from @sales s
      group by s.item_id, s.channel,
               format(saledate, 'yyyy-mm') as yyyymm,
     )
select iy.item_id, iy.yyyymm, c.channel, coalesce(icym.cnt, 0)
from (select distinct s.item_id, yyyymm from icym) iy cross join
     (select distinct channel from icym) c left join
     icym
     on icym.item_id = iy.item_id and icym.yyyymm = iy.yyyymm and
        icym.channel = c.channel;

答案 1 :(得分:1)

现在需要交叉加入!

DECLARE @sales table(
itemnumber int,
saledate date,
channeltype varchar(10),
ordid varchar, 
orditemqty int)

INSERT INTO @sales VALUES(43029, '2011-03-26', 'Channel2', 1, 5)
INSERT INTO @sales VALUES(43029, '2011-03-26', 'Channel2', 2, 6)
INSERT INTO @sales VALUES(43029, '2011-03-26', 'Channel2', 3, 2)
INSERT INTO @sales VALUES(43029, '2011-03-26', 'Channel2', 4, 3)
INSERT INTO @sales VALUES(43029, '2011-03-26', 'Channel2', 5, 1)
INSERT INTO @sales VALUES(43029, '2011-04-26', 'Channel2', 6, 5)
INSERT INTO @sales VALUES(43029, '2011-04-26', 'Channel2', 7, 7)
INSERT INTO @sales VALUES(43030, '2011-04-26', 'Channel1', 8, 8)
INSERT INTO @sales VALUES(43030, '2011-04-26', 'Channel2', 9, 1)
INSERT INTO @sales VALUES(43030, '2011-04-26', 'Channel1', 10, 2)
INSERT INTO @sales VALUES(43030, '2011-04-26', 'Channel2', 11, 4)
INSERT INTO @sales VALUES(43030, '2011-04-26', 'Channel2', 12, 6)
INSERT INTO @sales VALUES(43030, '2011-04-26', 'Channel2', 13, 1)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 14, 8)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 15, 9)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 16, 10)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 17, 11)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 18, 1)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 19, 4)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel2', 20, 7)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel2', 21, 9)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 22, 10)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 23, 11)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel1', 24, 10)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel2', 25, 1)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel2', 26, 4)
INSERT INTO @sales VALUES(43030, '2011-05-26', 'Channel2', 27, 6)
INSERT INTO @sales VALUES(43050, '2011-05-26', 'Channel1', 28, 8)
INSERT INTO @sales VALUES(43050, '2011-05-26', 'Channel2', 29, 9)
INSERT INTO @sales VALUES(43050, '2011-05-26', 'Channel1', 30, 1)
INSERT INTO @sales VALUES(43050, '2011-05-26', 'Channel2', 31, 4)
INSERT INTO @sales VALUES(43050, '2011-06-26', 'Channel1', 32, 9)
INSERT INTO @sales VALUES(43050, '2011-06-26', 'Channel1', 33, 1)
INSERT INTO @sales VALUES(43050, '2011-07-26', 'Channel1', 34, 6)
INSERT INTO @sales VALUES(43090, '2011-07-26', 'Channel2', 35, 3)
INSERT INTO @sales VALUES(43090, '2011-07-26', 'Channel2', 36, 4)
INSERT INTO @sales VALUES(43090, '2011-07-26', 'Channel2', 37, 5)
INSERT INTO @sales VALUES(43090, '2011-07-26', 'Channel2', 38, 8)
INSERT INTO @sales VALUES(43090, '2011-08-26', 'Channel1', 39, 2)
INSERT INTO @sales VALUES(43090, '2011-08-26', 'Channel1', 40, 3)
INSERT INTO @sales VALUES(43090, '2011-09-26', 'Channel1', 41, 5)

SELECT t.itemnumber, t.channeltype, 
right(convert(varchar, firstsaledate, 106), 8) AS firstsale, 
SUM(t.cnt) AS salecount, sum(t.qty) AS saleqty  
FROM 
    (
    SELECT fsdc.itemnumber, fsdc.firstsaledate, fsdc.channeltype, 
    CASE WHEN s.ordid IS NULL THEN 0 ELSE 1 END AS cnt, 
    COALESCE(s.orditemqty, 0) qty  
    FROM 
        (
        SELECT fsd.itemnumber, fsd.firstsaledate, fsd.targetdate, 
        c.channeltype 
        FROM
            (
            SELECT mns.itemnumber, mns.firstsaledate, DATEADD(m, 2, 
            DATEFROMPARTS(YEAR(mns.firstsaledate), MONTH(mns.firstsaledate), 1)) 
            as targetdate 
            FROM
                (
                SELECT itemnumber, Min(saledate) as firstsaledate  FROM @sales 
                GROUP BY itemnumber 
                ) mns
            ) fsd
            CROSS JOIN
                (
                SELECT DISTINCT channeltype FROM @sales
                ) c
        ) fsdc
    LEFT JOIN @sales s
        ON s.itemnumber = fsdc.itemnumber and s.channeltype = fsdc.channeltype 
        AND s.saledate < fsdc.targetdate
    ) t
GROUP BY t.itemnumber, t.channeltype, t.firstsaledate

结果

itemnumber  channeltype firstsale   salecount   saleqty
43029       Channel1    Mar 2011    0           0
43029       Channel2    Mar 2011    7           29
43030       Channel1    Apr 2011    11          84
43030       Channel2    Apr 2011    9           39
43050       Channel1    May 2011    4           19
43050       Channel2    May 2011    2           13
43090       Channel1    Jul 2011    2           5
43090       Channel2    Jul 2011    4           20

现在改变第一个时期所涵盖的月数是一件简单的事情。只需更改dateadd函数中的月数。

答案 2 :(得分:0)

您将需要所有不同的频道,然后像下面那样进行左连接..

;With cte
as
(select 
itemnumber,saledate,channeltype,
dense_rank() over (partition by  itemnumber order by cast(month(convert(datetime,saledate,103)) as varchar(2))+'/'+cast(year(convert(datetime,saledate,103)) as varchar(4))) as rownum
from
#temp
),
channel
as
(
select distinct channeltype from #temp)
select 
c.channeltype,
 itemnumber,
cast(month(convert(datetime,saledate,103)) as varchar(2))+'/'+cast(year(convert(datetime,saledate,103)) as varchar(4)) as datetimesale,
isnull(sum(rownum),0) as salescount
from channel c
left join
cte c1
on c.channeltype=c1.channeltype
where rownum=1
group by
itemnumber,
cast(month(convert(datetime,saledate,103)) as varchar(2))+'/'+cast(year(convert(datetime,saledate,103)) as varchar(4)),
c.channeltype