Sql-用于计算每月买家数量的查询

Sql-用于计算每月买家数量的查询,sql,sql-server,Sql,Sql Server,我真的需要您的帮助来创建一个查询,在这里我可以显示2017年1月至2017年12月期间一个月内订购超过1份订单的买家数量 此外,在未来12个月内没有再次订购的买家数量 下面是我的数据样本 日期 CID客户id 订单号 2017-02-03 0:23 924832 000023149 2017-02-05 0:11 924162 000092384 2017-07-01 0:53 914861 000023182 2017-08-09 0:42 924832 000021219 如果我理解正确的话

我真的需要您的帮助来创建一个查询,在这里我可以显示2017年1月至2017年12月期间一个月内订购超过1份订单的买家数量

此外,在未来12个月内没有再次订购的买家数量

下面是我的数据样本

日期 CID客户id 订单号 2017-02-03 0:23 924832 000023149 2017-02-05 0:11 924162 000092384 2017-07-01 0:53 914861 000023182 2017-08-09 0:42 924832 000021219
如果我理解正确的话,带有示例数据的表就是订单表,这意味着一行就是一个订单,具有唯一的OrderNo

如果是这样,则必须使用以下查询:

SELECT d.[MONTH], COUNT(distinct d.[Buyers with >1 order]) [Buyers with >1 order],
    COUNT(distinct d.[Buyers that didnt order for the next 12M]) [Buyers that didnt order for the next 12M]
FROM
(
    select c.[MONTH], c.[Date], c.CID, c.OrderNo,
            c.[Buyers with >1 order],
            case when c.[Buyers with >1 order] is not null and
                datediff(MONTH, c.[Date], LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])) > 12
                THEN C.CID END [Buyers that didnt order for the next 12M]
    from (
            SELECT b.[MONTH], b.[Date], b.CID, b.OrderNo,
                    case when COUNT(*) over (partition by b.[MONTH], b.CID) > 1 then b.CID end [Buyers with >1 order]
            FROM (
                    SELECT convert(date, DATEADD(month, DATEDIFF(month, 0, a.Date), 0)) [MONTH],
                            A.[Date], A.CID, A.OrderNo
                    FROM Orders a
                ) b
        ) c
) d
WHERE D.[MONTH] BETWEEN '2017-01-01' AND '2017-12-01'
GROUP BY d.[MONTH]
UPD:我刚刚注意到你的评论,澄清了在未来1200万年内没有订购的买家的含义:如果你在2017年1月订购,那么从2017年2月到2018年2月,你不应该有任何订单

对于这种情况,查询的部分

datediff(MONTH, c.[Date], LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])) > 12
应改为

DATEADD(DAY,1,EOMONTH(DATEADD(MONTH,13,C.[DATE]))) <= LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])
我在这里设置的


这应该与您的描述相匹配:

with cte as
 (
   select
      ca.ym
     ,cid
     -- flag buyers who made more than 1 order in a month
     ,case when count(*) > 1 then 1 else 0 end as multi_buy

     -- flag buyers that didn't order again within the next 12 months
     ,case when LEAD(ym,1,ym) -- month of next order
                over (partition by CID
                      order by ym) < DATEADD(month, 13, ym)
           then 0 
           else 1
      end as no_buy_within_range
   from orders
   CROSS APPLY 
    ( -- truncate the OrderDate to the 1st of month
      SELECT convert(Date, DATEADD(month, DATEDIFF(month, 0, OrderDate), 0)) as ym
    ) as ca
   group by
      ym
     ,cid
 )
select 
   ym
  ,sum(multi_buy)
  ,sum(no_buy_within_range)
from cte
group by ym
order by ym

我不明白。如何确定第一列?结果与样本数据有什么关系?应该是每月一次,比如2017-01-01年1月,2017-02-01年2月,等等。对于没有在第一列订购下一个1200万格式的买家来说,这意味着“yyyy-mm-dd hh:mm”。不确定这是否是您所指的。@Mr.Bhosale这就像是在接下来的12个月内没有再次订购的买家数量,就像如果您在2017年1月订购,您在2017年2月至2018年2月期间不应该有任何订单。
;WITH CTE AS
(
    select  CAST(DATEADD(month, DATEDIFF(month, 0, OrderDate), 0) as DATE) AS OrderMonth,
            CID,count(OrderNo) as OrderCount
    from Orders
    group by CAST(DATEADD(month, DATEDIFF(month, 0, OrderDate), 0) as DATE), CID
)
select q1.OrderMonth, q1.[MultipleOrderBuyers], q2.OrderedOverNext12Mo 
from
(
    select  OrderMonth, 
            SUM(CASE WHEN OrderCount > 1 THEN 1 ELSE 0 END) as [MultipleOrderBuyers]
    from CTE
    group by OrderMonth
)q1
LEFT OUTER JOIN
(
    select OrderMonth, SUM(OrderedOverNext12Mo) as OrderedOverNext12Mo
    from
    (
        select OrderMonth, CID, 
                (   select CASE WHEN SUM(OrderCount) > 1 THEN 1 ELSE 0 END 
                    from CTE 
                    where OrderMonth BETWEEN DATEADD(month,1,c1.OrderMonth) AND DATEADD(month,13,c1.OrderMonth)
                ) as OrderedOverNext12Mo
        from CTE c1
        group by OrderMonth, CID
    )c
    group by OrderMonth
)q2 on (q1.OrderMonth = q2.OrderMonth)
with cte as
 (
   select
      ca.ym
     ,cid
     -- flag buyers who made more than 1 order in a month
     ,case when count(*) > 1 then 1 else 0 end as multi_buy

     -- flag buyers that didn't order again within the next 12 months
     ,case when LEAD(ym,1,ym) -- month of next order
                over (partition by CID
                      order by ym) < DATEADD(month, 13, ym)
           then 0 
           else 1
      end as no_buy_within_range
   from orders
   CROSS APPLY 
    ( -- truncate the OrderDate to the 1st of month
      SELECT convert(Date, DATEADD(month, DATEDIFF(month, 0, OrderDate), 0)) as ym
    ) as ca
   group by
      ym
     ,cid
 )
select 
   ym
  ,sum(multi_buy)
  ,sum(no_buy_within_range)
from cte
group by ym
order by ym