我有一个成员(member)数据库,我想从中提取购买信息,但我不确定 SQL 中的最佳方法。我们出售订阅,即在固定时间段内进入我们健身房的入场券,例如。 3个月。成员(member)购买它们,当它们过期时,他们可以购买另一个。我们想选择一组成员,例如。前段时间购买了 3 个月通行证的学生,并确定他们的下一次订阅购买是什么(如果有的话)。
涉及三个表(有相关列):
- 订阅类型(ID、描述、持续时间)- 定义可以购买的订阅
- 订阅(MemberID、SubTypeID、StartDate、EndDate)- 购买实例,将成员与他们随时间购买的订阅类型相关联
- Members(ID, Type) - 成员数据,其中 Type 可以是 Student、Standard、Pensioner
因此,如果我想确定去年这个时候购买了 3 个月订阅的成员(member)的 ID,我可以使用如下内容:
SELECT MemberID, StartDate, EndDate
FROM Subscriptions s
INNER JOIN Members m
ON s.MemberID = m.ID
INNER JOIN SubscriptionTypes st
ON s.SubTypeID = st.ID
WHERE s.StartDate BETWEEN <period start> and <period end>
AND m.Type = 'Student'
AND st.Duration = 3
这给了我一组成员(以及他们去年购买的通行证的实际开始和结束日期)。
但是我如何从这个起点出发,然后在他们的 3 个月通行证到期后提取这些成员在一段时间内(比如 1 个月)的下一次订阅购买。我可以想出程序方法,例如。遍历上面集合中的每个成员并运行查询,但这不是 SQL 方式。
谁能给我一些指导?我想以原始组中的一组成员、他们的第一次购买订阅信息和第二次购买订阅信息(如果有的话)作为结尾。
最佳答案
由于您使用的是 SQL Server 2005,因此您拥有 ROW_NUMBER
的能力提供给你。我建议从类似的东西开始
SELECT MemberID, StartDate, EndDate,
ROW_NUMBER() OVER(PARTITION BY MemberID ORDER BY s.StartDate ASC)
AS SubscriptionSequence
FROM Subscriptions s
INNER JOIN Members m ON s.MemberID = m.ID
INNER JOIN SubscriptionTypes st ON s.SubTypeID = st.ID
WHERE @PeriodStart <= s.StartDate
AND m.Type = 'Student'
对于在 @PeriodStart
或之后开始订阅的每个 Student
成员,这将为您提供一行 every 订阅,以及指示日期排序的序列号。
所以如果有人先花 3 个月然后再花 1 个月,你会得到
TheMemberId Jul 1 2011 Sep 30 2011 1
TheMemberId Oct 1 2011 Oct 31 2011 2
无论是在进一步的查询细化中,还是在应用程序代码中,您都可以根据需要使用序列号。
注释:
概念行为是这样的:
- 确定所有满足
WHERE
条件的购买(即,在特定日期之后进行) - 按成员分组(即
PARTITION BY
) - 在每个成员组中,按日期对购买进行排序,并记下该组中的位置(即
ROW_NUMBER() OVER( ... ORDER BY )
) - 为每次购买发出一行,其中一列是订购的每个成员组中的位置(这是
SubscriptionSequence
)
如果您只对确实进行后续购买的成员(member)感兴趣,您可以这样做
SELECT MemberID, StartDate, EndDate,
ROW_NUMBER() OVER(PARTITION BY MemberID ORDER BY s.StartDate ASC)
AS SubscriptionSequence,
(SELECT COUNT(*) FROM Subscriptions ss
WHERE @PeriodStart <= ss.StartDate
AND ss.MemberID = m.ID) AS SubscriptionCount
FROM Subscriptions s
INNER JOIN Members m ON s.MemberID = m.ID
INNER JOIN SubscriptionTypes st ON s.SubTypeID = st.ID
WHERE @PeriodStart <= s.StartDate
AND m.Type = 'Student'
AND SubscriptionCount >= 2
我使用相关子查询 在每一行中包含一个列,该列计算该行中引用的成员进行的合格订阅的数量。
成员 ID 234 和 567 的示例输出:
234 Jul 1 2011 Sep 30 2011 1 2
234 Oct 1 2011 Oct 31 2011 2 2
567 Jul 1 2011 Sep 30 2011 1 3
567 Oct 1 2011 Oct 31 2011 2 3
567 Dec 1 2011 Dec 31 2011 3 3
这里的成员 234 有两个符合条件的订阅,而成员 567 有 3 个。只有一个符合条件的订阅的成员不会出现在第二个查询的输出中,因为 WHERE
子句。
关于sql - 在 SQL 中跟进购买查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9158302/