sql - 在 SQL 中跟进购买查询

标签 sql sql-server-2005 tsql

我有一个成员(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

无论是在进一步的查询细化中,还是在应用程序代码中,您都可以根据需要使用序列号。


注释:

概念行为是这样的:

  1. 确定所有满足WHERE条件的购买(即,在特定日期之后进行)
  2. 按成员分组(即 PARTITION BY)
  3. 在每个成员组中,按日期对购买进行排序,并记下该组中的位置(即 ROW_NUMBER() OVER( ... ORDER BY ))
  4. 为每次购买发出一行,其中一列是订购的每个成员组中的位置(这是 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/

相关文章:

sql-server - 将用户定义的 CLR 函数的执行限制为 sysadmin 而不是 dbowner

sql-server-2005 - 如果sql server 2005中的原始表不存在,则从一个表更新到另一个表

sql-server - T-SQL TRY CATCH 的问题?

sql-server-2008 - SQL Server 是否在运行之前验证存储的过程?

php - 向MySql表中依赖插入数据

php - SQL 查询出错,但数据库正在使用正确的信息进行更新

mysql - 如何更改 WAMP 上运行的 MySQL 中的只读变量

wpf - 从/向 SQL 保存和检索 RichTextBox.Document?

sql - 在mysql中左连接右表的条件

tsql - 在 ADO.NET 中使用多个 T-SQL 语句