Отслеживание запроса на покупку в SQL - PullRequest
3 голосов
/ 06 февраля 2012

У меня есть членская база данных, из которой я хотел бы извлечь информацию о покупке, но я не уверен в лучшем способе использования SQL.Мы продаем подписки, которые являются входными билетами в наш тренажерный зал на фиксированные периоды времени, например.3 месяца.Участники покупают их, и когда они истекают, они могут купить другого.Мы хотели бы выбрать группу участников, например.студенты, купившие трехмесячный пропуск, некоторое время назад, и определяют, какой была их следующая покупка по подписке, если таковая имеется.

В нее вовлечены три таблицы (с соответствующими столбцами):

  • SubscriptionTypes (ID, Описание, Длительность) - определяет, какие подписки можно приобрести
  • Подписки (MemberID, SubTypeID, StartDate, EndDate) - экземпляры покупок, связывает участника с типами подписок, которые они приобрели за время
  • Участники (ID, Тип) - данные участника, где Типом может быть Студент, Стандарт, Пенсионер

Так что, если я хочу определить идентификаторы участников, которые купили 3-месячную подписку по адресув это время года в прошлом году я мог использовать что-то вроде:

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

Это дает мне набор участников (и фактические даты начала и окончания пропусков, которые они купили в прошлом году).

Но как мне перейти с этой отправной точки, а затем извлечь следующую подписку на покупку для этих участников в период (скажем, 1 месяц) после их 3-мистекает срок действия.Я могу придумать процедурные методы, например.Выполните итерацию по каждому члену в указанном выше наборе и выполните запрос, но это не так, как SQL.

Кто-нибудь может дать мне какое-то руководство?Я хотел бы закончить с набором участников из исходного набора, их первой информацией о подписке на покупку и их второй (если есть).

Ответы [ 2 ]

2 голосов
/ 06 февраля 2012

Поскольку вы работаете с 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'

. Это даст вам, для каждого Student участника, у которого подписка начинается с или после @PeriodStart, строку для каждой подписки.вместе с порядковым номером, указывающим порядок даты.

Так, если кто-то взял 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)

Если выЗаинтересованы только в участниках, которые сделали совершившую последующую покупку, вы можете сделать

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:

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.

0 голосов
/ 06 февраля 2012

Он большой, но вы можете сделать что-то вроде этого:

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'

С помощью выбора вы делаете еще один равный выбор, но с внутренним соединением.С помощью внутреннего соединения вы получаете участников, которых вы хотите проверить, и конечную дату их ваучера.Таким образом, вы можете использовать эту конечную дату для внешнего запроса.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...