我正在努力解决这个问题。 我被要求创建一份报告,显示我们数据库中的回头客。
其中一个要求是,如果客户在特定日期有超过 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。 任何帮助将不胜感激。
您已经很接近了,您需要将
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;
如果您想将参数传递给查询并连接结果,这就是表值函数的用途。当您加入它时,您使用 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)
首先感谢大家的帮助。 @MaxSzczurek 建议我使用表值函数。经过更多研究后,我最终仅使用临时表来获取每个客户的不同购买日期。 然后我将其加载到与主表右连接的另一个临时表中。 这给了我我正在寻找的结果。 它有点(很多)丑陋,但它有效。
我用过:
dense_rank() over(按客户名称顺序按日期升序分区)
为了获得每个客户的购买顺序,但将同一客户同一天的多次购买计算为相同的购买数量(按顺序)。