在最新购买之前选择最新购买

时间:2019-03-19 15:19:27

标签: sql sql-server sql-server-2017

我有一个看起来像这样的表:

customer_id  purchase_date  category
1            9/1/2018       Electronics
1            9/2/2018       Art
1            9/3/2018       Books
1            9/5/2018       CPG
2            9/2/2018       Books
2            9/4/2018       Electronics
2            9/20/2018      CPG     

在这里,我试图得出CPG购买之前的最近购买。为了进一步说明,这是我的步骤:

步骤1.创建一个不在CPG类别中的购买表:

WITH OTHERS AS(
    SELECT customer_id,
           category as others_category,
           purchase_date
    FROM orders o
    WHERE category IN ('Electronics', 'Books', 'Art')
),

第2步。在CPG类别中创建购买表:

CPG AS( 
    SELECT customer_id,
           category as cpg_category,
           purchase_date
    FROM orders o
    WHERE category = 'CPG'
)

第3步:左加入: 这就是我卡住的地方。我想生成一个在CPG购买之前具有最近OTHER购买的表格。也就是说,输出应如下所示:

others_category  count_distinct_customers
Electronics            1
Books                  1

理想情况下,我不想使用CTE。 SQL类型是SQL Server 2017。

5 个答案:

答案 0 :(得分:1)

这就是我在SQL Server 2017中的处理方式,但是,我不确定这是否可以在2005年使用(不幸的是,就像我说的那样,我已经没有2005测试环境了)。我在SQL Server 2008中添加了 think CREATE FUNCTION [dbo].[CantidadDeContratos](@IdNegocio tinyint) RETURNS @tmpCantidadDeContratos TABLE ( CantidadContratos int , NumeroDocumento varchar(20) , CUIT varchar(20) ) AS BEGIN INSERT INTO @tmpCantidadDeContratos SELECT COUNT(con.idAutomovil) CantidadContratos , cli.NumeroDocumento, cli.CUIT FROM Contrato con INNER JOIN Cliente cli ON cli.idAutomovil = con.idAutomovil WHERE cli.idNegocio = @IdNegocio AND con.EstadoContrato4NH = 1 AND con.TipoContrato4NH != 3 GROUP BY cli.NumeroDocumento , cli.CUIT RETURN END GO 。当然,“ VTE”在2005年将无法运行,因为APPLY构造函数子句是在2008年添加的(如果我记得,正确),但是,您至少要有一张表进行测试:

VALUES

答案 1 :(得分:1)

换句话说,您只想要紧随其后的“ CPG购买”(由同一位客户购买?)的购买。

借助分析功能LEAD(),您可以查找“后续”行中的内容,而不必将数据重新加入自身。

WITH
  orders_with_lookup AS
(
  SELECT
    *,
    LEAD(category) OVER (PARTITION BY customer_id ORDER BY purchase_date)   AS customers_next_purchase_category
  FROM
    orders
)
SELECT
  category,
  COUNT(DISTINCT customer_id)   AS count_distinct_customers
FROM
  orders_with_lookup
WHERE
  customers_next_purchase_category = 'CPG'
GROUP BY
  category
ORDER BY
  category

答案 2 :(得分:0)

您可以使用OUTER APPLY(从SQL Server 2005开始可用)将每个CPG订单与其之前购买的OTHERS一起加入,然后可以仅返回该OTHERS订单数据。

我添加了一个DISTINCT,因此,如果两个CPG订单的其他前一个订单相同(因为在它们之间没有输入其他订单),则仅返回一次。

   SELECT DISTINCT others.*
   FROM orders cpg
        OUTER APPLY (SELECT top 1 others.*
                     FROM orders as others
                     WHERE category <> 'CPG' and
                           others.purchase_date < cpg.purchase_date
                           order by others.purchase_date desc) as others
   WHERE category = 'CPG'

答案 3 :(得分:0)

尝试一下

;WITH CTE(customer_id , purchase_date , category)
AS
(
SELECT 1,'9/1/2018' ,'Electronics' UNION ALL
SELECT 1,'9/2/2018' ,'Art'         UNION ALL
SELECT 1,'9/3/2018' ,'Books'       UNION ALL
SELECT 1,'9/5/2018' ,'CPG'         UNION ALL
SELECT 2,'9/2/2018' ,'Books'       UNION ALL
SELECT 2,'9/4/2018' ,'Electronics' UNION ALL
SELECT 2,'9/20/2018','CPG'     
)
,CTE2 
AS
(
SELECT customer_id,purchase_date,category, 
       ROW_NUMBER()OVER(PARTITION BY customer_id ORDER BY purchase_date DESC) AS MostRecentPurchase
FROM
(
SELECT customer_id , 
       CAST( purchase_date AS DATE) purchase_date, 
       category
FROM CTE
)dt
)
SELECT Category AS Others_category,
       COUNT(DISTINCT customer_id) AS Count_distinct_customers
FROM  CTE2
WHERE  MostRecentPurchase = 2
GROUP BY category

结果

Others_category     Count_distinct_customers
-----------------------------------------
Books                   1
Electronics             1

答案 4 :(得分:-1)

这是另一种方法...有很多方法可以给这只猫剥皮。

declare @Something table
(
    customer_id int
    , purchase_date date
    , category varchar(20)
)
insert @Something values
(1, '9/1/2018 ', 'Electronics')
, (1, '9/2/2018 ', 'Art')
, (1, '9/3/2018 ', 'Books')
, (1, '9/5/2018 ', 'CPG')
, (2, '9/2/2018 ', 'Books')
, (2, '9/4/2018 ', 'Electronics')
, (2, '9/20/2018', 'CPG')

, (3, '9/2/2018 ', 'Books') --added customer 3 
, (3, '9/4/2018 ', 'Electronics')
, (3, '9/20/2018', 'CPG')

select category
    , DistinctCustomerCount = count(*)
from
(
    select *
        , RowNum = row_number()over(partition by customer_id, case when category = 'CPG' then 1 else 0 end order by purchase_date desc)
    from @Something
) x
where x.category <> 'CPG'
    and x.RowNum = 1
group by x.category