上下文是一个包含date和UserAccount的事务表。该表包含大约十亿行。
dOperationValueDate sUserAccount
------------------- ----------------------------------------------
2016-03-05 00000000001
2016-03-06 00000000002
2016-03-07 00000000003
2016-03-08 00000000004
2016-03-09 00000000005
2016-04-05 00000000002
2016-10-05 00000000001
2016-10-06 00000000001
2016-10-06 00000000005
我想在我的表格中找到这些标准的数据:
在我的示例中,结果将是帐户2,3,4。
我开始使用LEFT OUTER JOIN,以便在6个月后删除所有带有事务的userId。但是处理时间非常糟糕:现在是4个小时。
SELECT b.sUserAccount FROM
(SELECT sUserAccount FROM T_Operations WITH (readuncommitted) WHERE dOperationValueDate < DATEADD(month, -6, DATEADD(month, DATEDIFF(month, 0, GETUTCDATE()), 0)) GROUP BY sUserAccount) b -- all operations before 6 months ago
LEFT JOIN
(SELECT sUserAccount FROM T_Operations WITH (readuncommitted) WHERE dOperationValueDate >= DATEADD(month, -6, DATEADD(month, DATEDIFF(month, 0, GETUTCDATE()), 0)) GROUP BY sUserAccount) c -- all operations since 6 months
ON b.sUserAccount = c.sUserAccount
WHERE c.sUserBankAccount IS NULL) d -- remove all customers who have operations before 6 months ago and since 6 months / keep only customers who have operations beofre 6 months ago only
我认为解决方案是在b查询中只找到一个操作,并且sql在找到一行时停止。主要问题是,如果用户在6个月之前没有交易,但对于其他用户,则会没事。
另一方面,我必须在6个月后检查每笔交易,以便将客户从范围中删除。
我读过CROSS APPLY,但我不确定它是如何工作的。
这里的主要问题是处理时间。我必须做一个“快速”请求(不到1小时)。
答案 0 :(得分:0)
我认为你应该可以在这里使用NOT EXISTS。
SELECT b.sUserAccount
FROM T_Operations b WITH (READUNCOMMITTED)
WHERE b.dOperationValueDate < DATEADD(month,-6,DATEADD(month,DATEDIFF(month,0,GETUTCDATE()),0))
AND NOT EXISTS ( SELECT 1
FROM T_Operations WITH (READUNCOMMITTED)
WHERE sUserAccount = b.sUserAccount
AND dOperationValueDate >= DATEADD(month,-6,DATEADD(month,DATEDIFF(month,0,GETUTCDATE()),0)) )
GROUP BY b.sUserAccount -- all operations before 6 months ago
或者实际上,您可以将GROUP BY与HAVING一起使用
SELECT sUserAccount
FROM T_Operations WITH (READUNCOMMITTED)
GROUP BY sUserAccount
HAVING MAX(dOperationValueDate) < DATEADD(month,-6,DATEADD(month,DATEDIFF(month,0,GETUTCDATE()),0))
作为旁注.. DATEADD(month,-6,DATEADD(month,DATEDIFF(month,0,GETUTCDATE()),0))
将返回2016-04-01
如果您想要当前日期,减去六个月,您可以使用DATEADD(month,-6,CAST(GETUTCDATE() AS DATE))
或DATEADD(month,-6,DATEADD(day,DATEDIFF(day,0,GETUTCDATE()),0)
答案 1 :(得分:0)
.fastq
在dOperationValueDate上有索引