问题
Following up on my last question, Counting Items based on First Month Sold, I need to count items by the first two months they were sold but also need to group by channel along with item, along with total item qty sold as well.
See sample code below
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)
The output would look like the following
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
A count would only appear if it was sold during the first two months within the first time the item was ordered, where it could be one of several channels (I'm using Channel1, and 2 as examples but there could be several) but will always have one channel.I'd want to display all channels and show a count of 0 if there isn't anything there with the quantity also being 0 in that case (example, an item sold in one channel during those first two months but not the second channel).
Thanks!
回答1:
This does need a cross join now!
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
Results
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
It is now a simple thing to change the number of months covered in the first period. Just change the number of months in the dateadd function.
回答2:
This seems a bit tricky. One method is to generate all the rows you want with a cross join
and then use a left join
to bring in the count:
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;
回答3:
You will need all distinct channels and then do a left join like below..
;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
来源:https://stackoverflow.com/questions/39068325/counting-by-item-channel-by-first-two-months-sold