SQL中的后续采购查询

SQL中的后续采购查询,sql,sql-server-2005,tsql,Sql,Sql Server 2005,Tsql,我有一个会员数据库,我想从中提取购买信息,但我不确定SQL中的最佳方法。我们出售订阅服务,这是进入我们健身房的入场证,期限固定,如3个月。会员购买,到期时可以购买另一个。我们想选择一组成员,例如不久前购买了3个月通行证的学生,并确定他们的下一次订阅购买是什么(如果有的话) 有三个表格涉及相关列: SubscriptionTypesID、描述、持续时间-定义可以购买的订阅 SubscriptionMemberId、SubsubId、StartDate、EndDate-购买实例,将成员与他们随时间购

我有一个会员数据库,我想从中提取购买信息,但我不确定SQL中的最佳方法。我们出售订阅服务,这是进入我们健身房的入场证,期限固定,如3个月。会员购买,到期时可以购买另一个。我们想选择一组成员,例如不久前购买了3个月通行证的学生,并确定他们的下一次订阅购买是什么(如果有的话)

有三个表格涉及相关列:

SubscriptionTypesID、描述、持续时间-定义可以购买的订阅 SubscriptionMemberId、SubsubId、StartDate、EndDate-购买实例,将成员与他们随时间购买的订阅类型链接 MembersID,Type-成员数据,其中类型可以是学生、标准、养老金领取者 因此,如果我想确定去年这个时候购买了3个月订阅的会员的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方法


谁能给我指点方向吗?最后,我想介绍原始组中的一组成员,他们的第一次购买订阅信息和第二次购买订阅信息(如果有)。

这是一个很大的问题,但您可以这样做:

SELECT m.MemberID, s.StartDate, s.EndDate
FROM Subscriptions s
INNER JOIN Members m
ON s.MemberID = m.ID
INNER JOIN SubscriptionTypes st
ON s.SubTypeID = st.ID

INNER JOIN (SELECT m.MemberID, s.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 a.EndDate and dateadd('m', 1, a.EndDate)
AND m.Type = 'Student'
AND st.Duration = 3) a on a.MemberID = m.MemberID

WHERE s.StartDate BETWEEN dateadd('m', 4, <period start>) and dateadd('m', 4, <period end>)
AND m.Type = 'Student'

使用select,您可以进行另一个相等的select,但其上有一个内部联接。通过内部联接,您可以获得要测试的成员及其凭证的结束日期。因此,您可以在外部查询中使用该结束日期。

因为您使用的是SQL Server 2005,所以您可以使用。我建议从以下几点开始

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'
无论是在进一步的查询细化中,还是在应用程序代码中,都可以根据需要使用序列号

解释性说明:

概念行为是这样的:

确定所有符合WHERE条件的购买,即在特定日期后进行的购买 按成员分组,这是分区依据 在每个成员组中,按日期订购采购,并注意该组中的位置,即上面的行号。。。订购人 为每次购买发出一行,其中一列是按成员排序的组中的位置,这是SubscriptionSequence 如果你只对后续购买的会员感兴趣,你可以这样做

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

在这里,成员234有两个符合条件的订阅,而成员567有3个。只有一个合格订阅的成员不会出现在第二个查询的输出中,因为WHERE子句中的最后一个术语。

谢谢您的回答。我还在想办法解决这个问题。你能告诉我,如果一个学生买了一张3个月的通行证,那会不会有争吵?就是说,没有第二次购买?谢谢你的回答。有几个问题:A你在第1行提到n.MemberID,那应该是m.MemberID吗?;b你用a指的是几列。作为前缀,在哪里定义了?c这是否忽略了购买3个月通行证的学生,而不包括其他学生,即只选择那些购买第二次通行证的学生?a是的,我编辑过。b是我用别名进行的内部查询c是的,只选择进行第二次查询的人。别名为a的内部查询选择购买通行证的成员,外部查询从购买其他通行证的成员中选择
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
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