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

标签 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 个月活跃”查询而不是“活跃”过去 6 个月也是如此。

最佳答案

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

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;

关于sql-server - 如何从计数不同的查询中过滤掉,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59350691/

相关文章:

SQL Server 文件流-删除 "speed"

sql - 如何使用一个表作为其他表的过滤器并在 sql 中生成一个新表

c# - 如何通过 SQL 中的列名检查单元格是否为空?

sql 选择计数 > 1 的记录,其中至少一条记录具有值

sql-server - SQL 计划作业查询,上次运行的持续时间?

sql-server - SQL 中减少行大小并没有减少表大小

c# - ADO.NET、SQL Server、C# : how to check if a certain parameter does not exist before performing an Insert in a database

sql - 根据 SQL-SERVER 中的空间交集更新行

tsql - LEFT() 与 LIKE 运算符之间的 T-SQL 速度比较

sql - 读取 JSON 数组作为 SQL 表列之一