我有一个产品表,如下所示:
vertical-align: middle
每当在该表中插入一行,就会表明有新产品被出售。
我只有3个ProductId(pKey) ProductTypeId
1 3
2 3
3 2
4 1
5 1
,它实际代表一台服务器,我的客户可以取消该服务器并取消其状态或将其保持为待命状态,这使我们看到了如下状态产品表的历史记录: >
ProductTypeId
我只有1,2,3 3种状态(“ ProductStatus”列)。
我的目标是每月计算状态为1的StatusId(pKey) ProductId StatusDate ProductStatus
1 ,1 ,1-1-17 ,1
2 ,1 ,2-12-17 ,2
3 ,2 ,21-5-17 ,1
4 ,3 ,11-5-18 ,1
5 ,2 ,18-5-18 ,2
6 ,2 ,10-8-18 ,3
的数量。
列ProducsType
代表状态更改的日期,因此,客户第一次购买产品/服务时,他/她将拥有StatusDate
(1,2或3),永远不会更改,并且ProductTypeId
为1,但将来可以随时更改。
查询结果应类似于:
ProductStatus
以此类推。...
答案 0 :(得分:2)
如果您一直在寻找列中的行和ProductTypeId常量。它将起作用。
SELECT * FROM ( SELECT YEAR(s.StatusDate) AS 'Year', MONTH(s.StatusDate) AS 'MONTH', p.ProductTypeId FROM Status s INNER JOIN Product p ON p.ProductId = s.ProductId WHERE s.ProductStatus = 1 GROUP BY p.ProductTypeId, s.StatusDate )p PIVOT ( COUNT(p.ProductTypeId) FOR p.ProductTypeId IN([1],[2],[3]) )AS Pb
答案 1 :(得分:0)
我还没有测试过查询,但是看起来应该像这样。
SELECT YEAR(h.StatusDate),MONTH(h.StatusDate),COUNT(p1.ProductId),
COUNT(p2.ProductId),COUNT(p3.ProductId)
FROM HistoryTable h
left join products p1 on p1.ProductId = h.ProductId and p1.ProductTypeId = 1
left join products p2 on p2.ProductId = h.ProductId and p2.ProductTypeId = 2
left join products p3 on p3.ProductId = h.ProductId and p3.ProductTypeId = 3
WHERE h.ProductStatus = 1
GROUP BY YEAR(h.StatusDate),MONTH(h.StatusDate)
答案 2 :(得分:0)
这很棘手。我更喜欢在特定的日期而不是一个月内计算值。这样可以防止一个月内对产品进行多次计数。
以下内容统计每个月第一天的状态。它可以扩展为一个月内的任何更改,但可能会重复计算单个产品:
select v.dte,
sum(case when h.status = 1 then 1 else 0 end) as status_1,
sum(case when h.status = 2 then 1 else 0 end) as status_2,
sum(case when h.status = 3 then 1 else 0 end) as status_3
from (values (convert(date, '2017-01-01')),
(convert(date, '2017-02-01')),
(convert(date, '2017-03-01')),
(convert(date, '2017-04-01')),
(convert(date, '2017-05-01')),
(convert(date, '2017-06-01'))
) v(dte) left join
(select h.*,
lead(status_date) over (partition by productid order by status_date) as end_status_date
from history h
) h
on v.dte >= h.status_date and
(v.dte < h.end_status_date or h.end_status_date)
group by v.dte
order by v.dte;