简体   繁体   English

Sql - 查询计算编号。 每月的买家

[英]Sql - Query to calculate no. of buyers monthly

i would really need your help in creating a query where i can show the number of buyers who made more than 1 order in a month for the period January 2017 to December 2017.我真的需要你的帮助来创建一个查询,我可以在其中显示 2017 年 1 月至 2017 年 12 月期间一个月内订购超过 1 个订单的买家数量。

Also, the no.此外,没有。 of these buyers that didn't order again within the next 12 months.这些买家中没有在接下来的 12 个月内再次订购。

Below is sample my data.以下是我的数据示例。

Date日期 CID (customer id) CID(客户 ID) OrderNo订单号
2017-02-03 0:23 2017-02-03 0:23 924832 924832 000023149 000023149
2017-02-05 0:11 2017-02-05 0:11 924162 924162 000092384 000092384
2017-07-01 0:53 2017-07-01 0:53 914861 914861 000023182 000023182
2017-08-09 0:42 2017-08-09 0:42 924832 924832 000021219 000021219

Output should be like this Output 应该是这样的

Month Buyers with >1 order > 1个订单的买家 Buyers that didnt order for the next 12M未订购下一个 12M 的买家
2017-01-01 2017-01-01 122 122 92 92
2017-02-01 2017-02-01 74 74 24 24
2017-03-01 2017-03-01 216 216 107 107

This should to match your description:这应该与您的描述相匹配:

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

If I understood correctly, the table with sample data is the table of Orders , which means that one row is one order with unique OrderNo.如果我理解正确的话,带有示例数据的表是Orders表,这意味着一行是一个具有唯一 OrderNo 的订单。

If so, then the following query would have to work:如果是这样,那么以下查询将必须工作:

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: I just noted your comment clarifying the meaning of "Buyers that didn't order for the next 12M": "if you ordered last January 2017, you shouldnt have any orders from Feb 2017 to Feb 2018" UPD:我刚刚注意到您的评论澄清了“没有为下一个 12M 订购的买家”的含义:“如果您在 2017 年 1 月订购,则从 2017 年 2 月到 2018 年 2 月您不应该有任何订单”

For such cases, the part of the query对于这种情况,查询的部分

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

ought to be altered to应该改成

DATEADD(DAY,1,EOMONTH(DATEADD(MONTH,13,C.[DATE]))) <= LEAD(c.[Date]) over (partition by c.[CID] order by c.[Date])

Then the full query would look like:然后完整的查询将如下所示:

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]

I made this setup here http://sqlfiddle.com/#!18/090ac/5我在这里做了这个设置http://sqlfiddle.com/#!18/090ac/5

;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)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM