如何从计数不同的查询中过滤掉

时间:2019-12-16 04:48:20

标签: sql-server tsql

我正在尝试计算过去3个月和6个月内活跃的客户数量。

SELECT COUNT (DISTINCT CustomerNo)
FROM SalesDetail
WHERE InvoiceDate > (GETDATE() - 180) AND InvoiceDate < (GETDATE() - 90)

SELECT COUNT (DISTINCT CustomerNo)
FROM SalesDetail
WHERE InvoiceDate > (GETDATE() - 90)

但是,基于上述查询,我​​将获得过去3个月和最近6个月都处于活动状态的客户数量,即使有重复的客户也是如此。

  • 客户A在过去3个月内购买了一次
  • 客户A在过去6个月内也购买了一次

我如何过滤客户,以便如果客户A在过去3个月和6个月内都处于活动状态,则只会在“过去3个月内处于活动状态”查询中,而不是在“活动中”也是在过去六个月内。

3 个答案:

答案 0 :(得分:1)

我这样解决这个问题 让我们考虑一下您有下表。您可能会有更多的列,但是对于想要的结果,我们只需要他们购买商品的 customer_id date

CREATE TABLE [dbo].[customer_invoice](
    [id] [int] IDENTITY(1,1) NOT NULL,
    [customer_id] [int] NULL,
    [date] [date] NULL,
 CONSTRAINT [PK_customer_invoice] PRIMARY KEY([id]);

我在此表上创建了此示例数据

INSERT INTO [dbo].[customer_invoice]
   ([customer_id]
   ,[date])
 VALUES
   (1,convert(date,'2019-12-01')),
   (2,convert(date,'2019-11-05')),
   (2,convert(date,'2019-8-01')),
   (3,convert(date,'2019-7-01')),
   (4,convert(date,'2019-4-01'));

我们不要试图直接跳到最终解决方案上,而是每次都要跳一次。

SELECT customer_id, MIN(DATEDIFF(DAY,date,GETDATE())) AS lastActiveDays
FROM customer_invoice GROUP BY customer_id;

上面的查询为您提供了每个客户活跃之前的天数

customer_id lastActiveDays
   1         15
   2         41
   3         168
   4         259

现在,我们将把此查询用作子查询,并添加一个新列 ActiveWithinCategory ,以便在以后的步骤中可以按列对数据进行分组。

SELECT customer_id, lastActiveDays,
    CASE WHEN lastActiveDays<90 THEN 'active within 3 months'
         WHEN lastActiveDays<180 THEN 'active within 6 months'
         ELSE 'not active' END AS ActiveWithinCategory 
FROM(
    SELECT customer_id, MIN(DATEDIFF(DAY,date,GETDATE())) AS lastActiveDays
    FROM customer_invoice GROUP BY customer_id
)AS temptable;

此查询为您提供以下结果

customer_id lastActiveDays  ActiveWithinCategory
   1              15        active within 3 months
   2              41        active within 3 months
   3             168        active within 6 months
   4             259        not active

现在将上述全部内容用作子查询,并使用 ActiveWithinCategory

对数据进行分组
SELECT ActiveWithinCategory, COUNT(*) AS NumberofCustomers FROM (
    SELECT customer_id, lastActiveDays,
        CASE WHEN lastActiveDays<90 THEN 'active within 3 months'
             WHEN lastActiveDays<180 THEN 'active within 6 months'
             ELSE 'not active' END AS ActiveWithinCategory 
    FROM(
        SELECT customer_id, MIN(DATEDIFF(DAY,date,GETDATE())) AS lastActiveDays
        FROM customer_invoice GROUP BY customer_id
    )AS temptable 
) AS FinalResult GROUP BY ActiveWithinCategory;

这是您的最终结果

ActiveWithinCategory    NumberofEmployee
active within 3 months      2
active within 6 months      1
not active                  1

如果要实现相同的目的是MySQL数据库 这是最终的查询

SELECT ActiveWithinCategory, count(*) NumberofCustomers FROM(
    SELECT MIN(DATEDIFF(curdate(),date)) AS lastActiveBefore,
           IF(MIN(DATEDIFF(curdate(),date))<90,
              'active within 3 months',
              IF(MIN(DATEDIFF(curdate(),date))<180,'active within 6 months','not active')
            ) ActiveWithinCategory
    FROM customer_invoice GROUP BY customer_id
) AS FinalResult GROUP BY ActiveWithinCategory;

答案 1 :(得分:0)

我怀疑您要在此处进行条件聚合:

SELECT
    CustomerNo,
    COUNT(CASE WHEN InvoiceDate > GETDATE() - 90 THEN 1 END) AS cnt_last_3,
    COUNT(CASE WHEN InvoiceDate > GETDATE() - 180 AND InvoiceDate < GETDATE() - 90
               THEN 1 END) AS cnt_first_3
FROM yourTable
GROUP BY
    CustomerNo;

这里cnt_last_3是最近3个月的计数,cnt_first_3是从6个月前到3个月前的3个月内的计数。

答案 2 :(得分:0)

如果您想要不重复计数,可以像这样添加不重复

Select 
 count( Case when dt between getdate()- 90 and getdate()  then id else null end) cnt_3_months
,count(distinct Case when dt between getdate() - 180 and getdate() - 90 then id  else null end) cnt_6_months
from a