1

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

其中一项要求是,如果客户在特定日期有超过 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。任何帮助将不胜感激。

4

3 回答 3

0

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

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

WHERE s.PurchaseDate <> '' 

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

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

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)
于 2017-11-16T23:07:24.503 回答
0

您已经接近了,您需要distinct进入您的having条款,因为您只想包括具有超过 1 个不同购买日期的客户。

此外,仅按客户 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;
于 2017-11-17T02:13:12.630 回答
0

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

于 2017-11-19T19:18:34.067 回答