Sql 如何找到相隔6个月以上购买产品A和D的客户?

Sql 如何找到相隔6个月以上购买产品A和D的客户?,sql,tsql,Sql,Tsql,我需要更高级的SQL专家对此提供建议 我被要求创建一份报告,显示购买产品105的客户,以及6个多月后购买产品312的客户 例如,我有以下订单表: 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

我需要更高级的SQL专家对此提供建议

我被要求创建一份报告,显示购买产品105的客户,以及6个多月后购买产品312的客户

例如,我有以下订单表:

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
我是否需要使用游标并逐个记录地迭代,边走边比较日期

如果是这样,游标过程会是什么样子?我没有使用过游标,尽管我已经做了多年的程序编程


谢谢

类似的方法可能会奏效:

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
上述查询是对您的需求的简单解释,其中A105和D312的任何购买都发生在6个月之前。如果客户购买了

A 1月, A在3月份, 7月份买了一个,然后又买了一个 在9月举行了一次会议 对于客户一月和三月,它将返回两行,因为这两行后面都是6个多月后的D购买

下面的查询将查找最后一次A购买是在第一次D购买之前6个月或更长时间的所有情况

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, 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

你在上面有一些很好的答案;自我连接是一种方式。我想建议你如何最好地思考这样的问题。如果您在不同的表格中购买了产品A和D,会怎么样?并不是说你应该这样存储数据,而是你应该这样考虑数据。如果您这样做了,您可以加入,比如说,在客户ID上的product_a_购买到product_d_购买,并比较日期。因此,出于查询的目的,这就是您需要生成的内容。不是一个实际的磁盘上表,它是产品a_购买,而是一个来自您的购买表的记录表,其中只包括产品a购买,产品D也是如此。这就是自连接的原因。

Andy,谢谢。但这给了我:模棱两可的列名“CustID”。谢谢你。多么周到、全面的回答啊!我很感激。我会研究的。卡尔,谢谢你。这真的有助于我理解what背后的原因。我感谢你抽出时间来提供这一更深入的评论,以帮助我。
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
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