SQL 搜索多个日期范围内出现的交易类型
Posted
技术标签:
【中文标题】SQL 搜索多个日期范围内出现的交易类型【英文标题】:SQL search for occurrences of transaction types within multiple date ranges 【发布时间】:2020-10-13 21:04:39 【问题描述】:我有以下表格:
CREATE TABLE Users
(
UserID INT,
UserName VARCHAR(100)
)
CREATE TABLE Trans
(
UserID INT,
TransID INT,
TransTypeID INT,
TransDate DATETIME,
TransAmount DECIMAL(15,2)
)
CREATE TABLE TransType
(
TransTypeID INT,
TransTypeName VARCHAR(10)
)
为了简单起见,TransType 表中只有 2 个条目:
-
收入
费用
我正在寻找是否有 3 次或更多类型为收入的交易和 3 次或更多类型为费用的交易在特定时间段内发生在特定用户的日期范围内。
例如,我的搜索可能有以下变量:
DECLARE @StartDate DATETIME = '2018-06-30'
DECLARE @EndDate DATETIME = '2019-09-30'
DECLARE @SearchPeriodMonths INT = 6
我当前的解决方案从 @StartDate 到 @EndDate 以 6 个月的块(由 @SearchPeriodMonths 定义)搜索,如果存在 3 个或更多的收入和费用交易,则需要在表中返回。此解决方案效率不高,并且涉及使用游标。我希望有更好的方法。
CREATE TABLE #Results
(
UserID int,
StartDate DATETIME,
EndDate DATETIME,
Message VARCHAR(255)
)
DECLARE @UserID INT
DECLARE crUser CURSOR FOR
SELECT UserID
FROM Users
OPEN crUser
FETCH NEXT FROM crUser INTO @UserID
WHILE @@FETCH_STATUS = 0
BEGIN
DECLARE @DateCount TABLE(UserID INT, StartDate DATETIME, EndDate DATETIME, IncomeCount INT, ExpenseCount INT)
WHILE(@StartDate < @EndDate)
BEGIN
SELECT @StartDate = DATEADD(DAY, 1, @StartDate)
INSERT INTO @DateCount
SELECT
@UserID AS UserID,
@StartDate AS StartDate,
DATEADD(MONTH, @SearchPeriodMonths, @StartDate) AS EndDate,
(SELECT COUNT(*) FROM Trans WHERE TransTypeID = 1 AND UserID = @UserID
AND TransDate BETWEEN @StartDate and DATEADD(MONTH, @SearchPeriodMonths, @StartDate)
AS IncomeCount,
(SELECT COUNT(*) FROM Trans WHERE TransTypeID = 2 AND UserID = @UserID
AND TransDate BETWEEN @StartDate and DATEADD(MONTH, @SearchPeriodMonths, @StartDate)
AS ExpenseCount
END
INSERT INTO #Results
SELECT
@UserID AS UserID,
MIN(StartDate) AS StartDate,
MAX(EndDate) AS EndDate,
'3 or more Income and Expense transaction types occur in a 6 month period between '
+ convert(varchar, min(StartDate), 106) + ' and '
+ convert(varchar, max(EndDate), 106) AS WarningMessage
FROM @DateCount
WHERE IncomeCount > 2 AND ExpenseCount > 2
FETCH NEXT FROM crUser INTO @UserID
END
CLOSE crUser
DEALLOCATE crUser
-- Output query
SELECT *
FROM #Results
END
我仅限于在 SQL Server 2008 R2 中执行此操作。有没有更有效的方法来做到这一点而不涉及使用游标?
【问题讨论】:
【参考方案1】:我正在寻找是否有 3 次或更多类型为收入的交易和 3 次或更多类型为费用的交易发生在特定用户的特定日期范围内的特定时间段内。
使用聚合!
select userid
from trans
where transdate between @startdate and dateadd(month, @SearchPeriodMonths, @StartDate)
group by userid
having sum(case when transtypeid = 1 then 1 else 0 end) >= 3 and
sum(case when transtypeid = 2 then 1 else 0 end) >= 3;
【讨论】:
以上是关于SQL 搜索多个日期范围内出现的交易类型的主要内容,如果未能解决你的问题,请参考以下文章
SQL在where语句中使用日期范围的选择子查询来确定该日期范围内的最大值