【问题标题】:Counting by Item & Channel by First Two Months Sold按销售的前两个月按项目和渠道计数
【发布时间】:2016-12-28 08:14:25
【问题描述】:

跟进我的最后一个问题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 和 Channel 2 作为示例,但可能有多个) 但总是有一个频道。我想显示所有频道并显示计数为 0,如果在这种情况下没有任何数量也为 0 的情况(例如,在第一个频道中销售的商品两个月,但不是第二个频道)。

谢谢!

【问题讨论】:

    标签: sql tsql sql-server-2016


    【解决方案1】:

    这似乎有点棘手。一种方法是使用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;
    

    【讨论】:

      【解决方案2】:

      现在确实需要交叉连接!

      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 函数中更改月数即可。

      【讨论】:

      • 问题 - 我将如何从第一次购买的前两个月获得结果而不是第一个月?
      • 您希望前两个月的销售额相加,还是第一个月的销售额和第二个月的销售额相加?
      • 前两个月的总和
      • 除非前两个月分开可能最有意义,否则我总是可以汇总
      • 我的荣幸。很高兴能帮上忙。
      【解决方案3】:

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

      ;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
      

      【讨论】:

      • 我一定是重新命名错误。如果表名为 Orders,列名为 ItemNo、ChanType 和 OrderDate,则需要在查询中交换什么?我在尝试运行它时遇到了一些无效的列名错误,以为我已经正确替换了所有内容。
      • saledate for orderdate,chantype-channeltype,itemno 保持不变
      • 查询运行,但它显示给定项目的第一个订单是在 2015 年 1 月,每个渠道的正确计数,但是当我第一次检查数据时,该项目售出的时间是 2013 年,然后又是2014. 我能提供什么有助于诊断?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-09-27
      • 1970-01-01
      • 2016-12-28
      • 1970-01-01
      • 1970-01-01
      • 2023-01-19
      • 1970-01-01
      相关资源
      最近更新 更多