Как найти клиентов, которые купили продукт A и D с интервалом> 6 месяцев? - PullRequest
5 голосов
/ 10 февраля 2011

Мне нужен совет от более опытных экспертов SQL по этому вопросу.

Меня просят создать отчет, показывающий клиентов, которые купили Продукт 105 и , которые затем купили Продукт 312 более чем через 6 месяцев .

Например, у меня есть следующая таблица заказов:

RecID   CustID   ProdID   InvoiceDate
  1       20      105      01-01-2009
  2       20      312      01-04-2009
  3       20      300      04-20-2009
  4       31      105      07-10-2005
  5       45      105      10-03-2007
  6       45      300      11-10-2007
  7       45      312      08-25-2008

Мне нужен отчет, который просматривает эту таблицу и возвращается с:

CustID   ElapsedDays
  45        327

Нужно ли использовать курсор и повторять запись по записи, сравнивая даты на ходу?

Если это так, как будет выглядеть процедура курсора? Я не работал с курсорами, хотя я занимался годами процедурного программирования.

Спасибо!

Ответы [ 4 ]

2 голосов
/ 10 февраля 2011

Вы получили несколько хороших ответов выше;Самостоятельное объединение - это путь.Я хочу предложить вам, как лучше подумать о такой проблеме.Что если у вас были покупки Продуктов A и D в разных таблицах?Не то чтобы вы хранили данные таким образом, но вы должны думать о данных таким образом.Если вы это сделали, вы могли бы присоединиться, скажем, product_a_purchases к product_d_purchases по идентификатору клиента и сравнить даты.Итак, для целей вашего запроса , это то, что вам нужно произвести.Не фактическая таблица на диске, которая является product_a_purchases, а таблица записей из вашей таблицы покупок, которая включает в себя только покупки Продукта A, и то же самое для Продукта D. Вот где происходит самостоятельное соединение.

1 голос
/ 10 февраля 2011
select A.CustID, ElapsedDays = datediff(d, A.InvoiceDate, B.InvoiceDate)
from Orders A
inner join Orders B on B.CustID = A.CustID
    and B.ProdID = 312
    -- more than 6 months ago
    and B.InvoiceDate > dateadd(m,6,A.InvoiceDate)
where A.ProdID = 105

Приведенный выше запрос является простой интерпретацией вашего требования, когда ЛЮБАЯ покупка A (105) и D (312) происходила с интервалом в 6 месяцев. Если клиент приобрел

  • А в январе
  • А в марте
  • А в июле, а затем приобрел
  • D в сентябре

для клиента будет возвращено 2 строки (январь и март), поскольку за ними следует покупка D более чем через 6 месяцев.

Следующий запрос вместо этого находит все случаи, когда ПОСЛЕДНЯЯ покупка совершается за 6 месяцев или более до покупки FIRST D.

select A.CustID, ElapsedDays = datediff(d, A.InvoiceDate, B.InvoiceDate)
from (
    select CustID, Max(InvoiceDate) InvoiceDate
    from Orders
    where ProdID = 105
    group by CustID) A
inner join (
    select CustID, Min(InvoiceDate) InvoiceDate
    from Orders
    where ProdID = 312
    group by CustID) B on B.CustID = A.CustID
    -- more than 6 months ago
    and B.InvoiceDate > dateadd(m,6,A.InvoiceDate)

И если для того же сценария, описанного выше, вы не хотите видеть этого клиента, потому что покупки A (Jul) и D (Sep) не разделены на 6 месяцев, вы можете исключить их из первого запроса, используя EXISTS фильтр.

select A.CustID, ElapsedDays = datediff(d, A.InvoiceDate, B.InvoiceDate)
from Orders A
inner join Orders B on B.CustID = A.CustID
    and B.ProdID = 312
    -- more than 6 months ago
    and B.InvoiceDate > dateadd(m,6,A.InvoiceDate)
where A.ProdID = 105
  AND NOT EXISTS (
    SELECT *
    FROM Orders C
    WHERE C.CustID=A.CustID
    AND C.InvoiceDate > A.InvoiceDate
    and C.InvoiceDate < B.InvoiceDate
    and C.ProdID in (105,312))
1 голос
/ 10 февраля 2011

Вы можете сделать это с помощью самостоятельного объединения:

select a.custid, DATEDIFF(dd, a.invoicedate, b.invoicedate) 
from #t a
inner join #t b 
    on a.custid = b.custid 
        and a.prodid = 105 
        and b.prodid = 312 
where DATEDIFF(dd, a.invoicedate, b.invoicedate) > 180

Первое использование #t (с псевдонимом a) для первого продукта, а второе использование #t (с псевдонимом b) длявторой продукт.Вот скрипт, который я использовал для его проверки:

create table #t (
   recid int,
   custid int,
   prodid int,
   invoicedate date)

insert into #t select 1, 20, 105, '1/1/2009'
insert into #t select 2, 20, 312,'1/4/2009'
insert into #t select 3, 20, 300,'4/20/2009'
insert into #t select 4, 31, 105,'7/10/2005'
insert into #t select 5, 45, 105,'10/3/2007'
insert into #t select 6, 45, 300,'11/10/2007'
insert into #t select 7, 45, 312,'8/25/2008'

select a.custid, DATEDIFF(dd, a.invoicedate, b.invoicedate) 
from #t a
join #t b 
    on a.custid = b.custid 
        and a.prodid = 105 
        and b.prodid = 312 
where DATEDIFF(dd, a.invoicedate, b.invoicedate) > 180

drop table #t
0 голосов
/ 10 февраля 2011

Возможно, что-то вроде этого будет работать:

select CustID, datediff(day, O1.InvoiceDate, O2.InvoiceDate) as ElapsedDays
from Orders O1
   inner join Orders O2 
       on  O1.CustId = O2.CustId
       and dateadd(month, 6, O1.InvoiceDate) <= O2.InvoiceDate
where
   O1.ProdId = 105
   and O2.ProdId = 312
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...