我有一个看起来像这样的表:
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。
答案 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