查询日期和状态之间的计数

时间:2019-04-11 08:25:13

标签: sql sql-server

我有一个产品表,如下所示:

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

以此类推。...

3 个答案:

答案 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;