这是第一个解决方案,可以用作工作基础。
CREATE TABLE #orders(OrderId int identity(1,1), CustNum int, Orderdate date)
-- using system columns to populate demo data (I'm lazy)
INSERT INTO #orders(CustNum,Orderdate)
SELECT system_type_id, DATEADD(month,column_id*-1,GETDATE())
FROM sys.all_columns
-- Possible Solution 1:
-- Getting all your customers who haven't placed an order in the last 2 months
SELECT *
FROM (
-- All your customers
SELECT DISTINCT CustNum
FROM #orders
EXCEPT
-- All customers who have a transaction in the last 2 months
SELECT DISTINCT CustNum
FROM #orders
WHERE Orderdate >= DATEADD(month,-2,GETDATE())
) dat
DROP TABLE #orders
基于客户表可用的事实,这也可以是一个解决方案:
CREATE TABLE #orders(OrderId int identity(1,1), CustNum int, Orderdate date)
-- using system columns to populate demo data (I'm lazy)
INSERT INTO #orders(CustNum,Orderdate)
SELECT system_type_id, DATEADD(month,column_id*-1,GETDATE())
FROM sys.all_columns
CREATE TABLE #customers(CustNum int)
-- Populate customer table with demo data
INSERT INTO #customers(CustNum)
SELECT DISTINCT custNum
FROM #orders
-- Possible Solution 2:
SELECT
COUNT(*) as noTransaction
FROM #customers as c
LEFT JOIN(
-- All customers who have a transaction in the last 2 months
SELECT DISTINCT CustNum
FROM #orders
WHERE Orderdate >= DATEADD(month,-2,GETDATE())
) t
ON c.CustNum = t.CustNum
WHERE t.CustNum IS NULL
DROP TABLE #orders
DROP TABLE #customers
您将收到过去 2 个月内未购买任何商品的每位客户的计算价值。正如我所读到的,您尝试定期运行此查询(可能是针对特殊时事通讯或类似的东西)。如果您不计算,您将获得可用于进一步处理的客户编号。
滚动月份的解决方案
清除问题后,这应该是您正在寻找的东西。它会根据滚动月份生成输出。
CREATE TABLE #orders(OrderId int identity(1,1), CustNum int, Orderdate date)
-- using system columns to populate demo data (I'm lazy)
INSERT INTO #orders(CustNum,Orderdate)
SELECT system_type_id, DATEADD(month,column_id*-1,GETDATE())
FROM sys.all_columns
CREATE TABLE #customers(CustNum int)
-- Populate customer table with demo data
INSERT INTO #customers(CustNum)
SELECT DISTINCT custNum
FROM #orders
-- Possible Solution with rolling months:
-- first of all, get all available months
-- this can be also achieved with an temporary table (which may be better)
-- but in case, that you can't use an procedure, I'm using the CTE this way.
;WITH months AS(
SELECT DISTINCT DATEPART(month,orderdate) as allMonths,
DATEPART(year,orderdate) as allYears
FROM #orders
)
SELECT m.allMonths,m.allYears, monthyCustomers.noBuyer
FROM months m
OUTER APPLY(
SELECT N'01/'+m.allMonths+N'/'+m.allYears as monthString, COUNT(c.CustNum) as noBuyer
FROM #customers as c
LEFT JOIN(
-- All customers who have a transaction in the last 2 months
SELECT DISTINCT CustNum
FROM #orders
-- to get the 01/01/2015 out of 03/2015
WHERE Orderdate BETWEEN DATEADD(month,-2,
CONVERT(date,N'01/'+CONVERT(nvarchar(max),m.allMonths)
+N'/'+CONVERT(nvarchar(max),m.allYears)))
-- to get the 31/03/2015 out of the 03/2015
AND DATEADD(day,-1,
DATEADD(month,+1,CONVERT(date,N'01/'+
CONVERT(nvarchar(max),m.allMonths)+N'/'+
CONVERT(nvarchar(max),m.allYears))))
-- NOTICE: the conversion to nvarchar is needed
-- After extracting the dateparts in the CTE, they are INT not DATE
-- A explicit conversion from INT to DATE isn't allowed
-- This way we cast it to NVARCHAR and convert it afterwards to DATE
) t
ON c.CustNum = t.CustNum
WHERE t.CustNum IS NULL
-- optional: Count only users which were present in the counting month.
AND t.CustRegdate >= CONVERT(date,N'01/'+CONVERT(nvarchar(max),m.allMonths)+N'/'+CONVERT(nvarchar(max),m.allYears))
) as monthyCustomers
ORDER BY m.allYears, m.allMonths
DROP TABLE #orders
DROP TABLE #customers