【问题标题】:Repeat Customers with multiple purchases on the same day counts a 1同一天多次购买的回头客计为 1
【发布时间】:2017-11-16 22:50:07
【问题描述】:

我正试图解决这个问题。我被要求创建一个报告,显示我们数据库中的回头客。

其中一项要求是,如果客户在特定日期有超过 1 个订单,则仅计为 1 个。 然后,如果他们有超过 1 个购买日期,他们就会算作回头客。

在这里搜索,我发现这适用于查找在特定购买日期购买超过 1 次的客户。

SELECT DISTINCT s.[CustomerName], s.PurchaseDate

FROM Reports.vw_Repeat s WHERE s.PurchaseDate <> ''    

GROUP BY s.[CustomerName] , cast(s.PurchaseDate as date)

HAVING COUNT(*) > 1;

此 MSSQL 代码的工作方式与应有的一样,它显示了在同一日期购买了 1 次以上的客户。 我的问题是最好的方法是将它加入另一个查询(这是我需要帮助的地方),然后显示一个完整的重复客户列表,其中将返回超过 1 次购买的客户。

我正在使用 MSSQL。任何帮助将不胜感激。

【问题讨论】:

  • 您要加入的另一个查询在哪里?
  • 抱歉,我没有写出查询。我假设我必须将第一个查询包含在另一个查询中才能完成我正在尝试做的事情。我还是新手,不知道进行第二个查询的最佳途径。
  • 删除不同的,它在该查询中没有任何用处

标签: sql-server repeat customer


【解决方案1】:

您已经接近了,您需要将distinct 移动到您的having 子句中,因为您只想包含具有多个不同购买日期的客户。

此外,仅按客户 ID 分组,因为不同的日期必须属于同一组,count distinct 才能工作。

SELECT s.[CustomerName], COUNT(distinct cast(s.PurchaseDate as date))
FROM Reports.vw_Repeat s WHERE s.PurchaseDate <> ''    
GROUP BY s.[CustomerName] 
HAVING COUNT(distinct cast(s.PurchaseDate as date)) > 1;

【讨论】:

  • 我试过了,它也返回了 0 行。我在上面的问题中的查询确实返回了行。不过,您的示例似乎很有希望。
  • 你能展示一些select CustomerName, cast(s.PurchaseDate as date) 的样本数据吗?我想知道演员表是否正常工作
  • 这里是返回的一些示例数据。客户名称已与 vw_Repeat 中的邮政编码相连;我编辑了客户名称: xxxx - 95688 2016-01-13 xxxx - 91773 2016-02-01 xxxx - 29201 2016-02-17 xxxx - 72730 2016-03-25 xxxx - 30330 2016-03-30
  • 似乎不需要演员表。我删除了演员表,第一个查询仍然有效。但是你建议的那个没有。虽然它是有道理的,但我不明白为什么它不会返回任何东西。不过,我感谢您的帮助。
  • 如果我从 SELECT 语句中的 COUNT 中删除 DISTINCT,这似乎有效。 SELECT s.[CustomerName], COUNT(s.PurchaseDate) FROM Reports.vw_Repeat s WHERE s.PurchaseDate &lt;&gt; '' GROUP BY s.[CustomerName] HAVING COUNT(distinct s.PurchaseDate) &gt; 1; 并从 PurchaseDate 中删除 CAST。到目前为止,这似乎工作......需要抽查。
【解决方案2】:

如果您想将参数传递给查询并连接结果,这就是表值函数的用途。当你加入它时,你使用 CROSS APPLY 或 OUTER APPLY 而不是 INNER JOIN 或 LEFT JOIN。

另外,我认为这是不言而喻的,但是当您检查 PurchaseDate 是否为空时:

WHERE s.PurchaseDate <> '' 

那里可能有问题...这意味着它是一个 varchar 字段而不是日期时间(是吗?)并且不处理空值。至少,您可能希望将其替换为 ISNULL(s.PurchaseDate, '') ''。如果它实际上是日期时间,请使用 IS NOT NULL 而不是 ''。

(已编辑以添加示例数据和 DDL 语句。我建议将这些添加到 SQL 帖子中以帮助回答者。另外,由于查询中的字符串比较,我购买了一个 varchar 而不是日期时间。)

https://technet.microsoft.com/en-us/library/ms191165(v=sql.105).aspx

CREATE TABLE company (company_name VARCHAR(25))
INSERT INTO company VALUES ('Company1'), ('Company2')

CREATE TABLE vw_repeat (customername VARCHAR(25), purchasedate VARCHAR(25), company VARCHAR(25))
INSERT INTO vw_repeat VALUES ('Cust1', '11/16/2017', 'Company1')
INSERT INTO vw_repeat VALUES ('Cust1', '11/16/2017', 'Company1')
INSERT INTO vw_repeat VALUES ('Cust2', '11/16/2017', 'Company2')

CREATE FUNCTION [dbo].tf_customers
(
    @company varchar(25)    
)
RETURNS TABLE AS RETURN
(
    SELECT s.[CustomerName], cast(s.PurchaseDate as date) PurchaseDate
    FROM vw_Repeat s 
    WHERE s.PurchaseDate <> '' AND s.Company = @company 
    GROUP BY s.[CustomerName] , cast(s.PurchaseDate as date)
    HAVING COUNT(*) > 1
)
GO

SELECT * 
FROM company c
CROSS APPLY tf_customers(c.company_name)

【讨论】:

  • 删除 distinct,它在该查询中没有任何用处....group by 做什么? (使行唯一)“不同”做什么? (使行唯一)先完成哪个? (分组).....
  • @MaxSzczurek 建议删除 distinct
  • @MaxSzczurek :我想我做错了什么,因为它没有返回任何行。如果你有时间,我有几个问题。我重新编辑了我发布的初始 SQL 并删除了 Company 方面,因为我可以在最终的 SELECT/WHERE 语句中这样做,它最初只是用于缩小返回的数据。那么这将如何影响 SQL 呢?需要明确的是,您发布的 SQL 是我执行它的方式,让公司参与其中。
  • @Used_By_Already 是的!删除了不同的 - 我修复了分组但忘记删除它。 :)
  • @triton_9000 检查编辑 - 我添加了示例 DDL 和 DML 语句。这将返回具有给定样本数据的行。也许这可以为您解决问题。
【解决方案3】:

首先感谢大家的帮助。 @MaxSzczurek 建议我使用表值函数。在进一步研究之后,我最终只使用了一个临时表来获取每个客户的 DISTINCT 购买日期。然后我将它加载到另一个临时表 RIGHT JOINED 到主表。这给了我想要的结果。它有点(很多)丑陋,但它有效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-09-14
    • 2022-10-12
    • 1970-01-01
    • 2023-03-13
    • 2021-09-15
    • 1970-01-01
    • 2023-03-24
    相关资源
    最近更新 更多