我正在尝试编写一个SQL查询,该查询显示每位进行两次或两次以上购买的客户,查看购买的第一个和最后一个产品:
custumerID | Product ID First purchase | Product ID Last purchase
10 | 286 | 448
1033 | 244 | 138
11 | 265 | 299
我成功显示了所有进行过两次或两次以上购买的客户,包括ProductID和日期:
SELECT Customer_ID, Order_Date, Product_ID
FROM Orders
WHERE Customer_ID IN
(SELECT Customer_ID FROM Orders
GROUP BY Customer_ID
HAVING COUNT(*) >= 2)
ORDER BY Customer_ID, (CONVERT(datetime,Order_Date))
如何选择聚合中的第一行和最后一行,并创建其中的两列?
答案 0 :(得分:2)
由于您具有同一日期的最大和最小购买日期(客户ID = 10),所以如果第一列是我估计具有自动增量的ID,则可以使用以下脚本获得所需的输出-
SELECT
Customer_ID,
(SELECT Order_ID FROM your_table WHERE ID =MIN(A.ID)) [Product ID First purchase],
(SELECT Order_ID FROM your_table WHERE ID=MAX(A.ID)) [Product ID Last purchase]
FROM your_table A
GROUP BY Customer_ID
答案 1 :(得分:1)
这里是使用COUNT
和ROW_NUMBER
作为分析函数的一种方法。
WITH cte AS (
SELECT Customer_ID, Order_Date, Product_ID,
COUNT(*) OVER (PARTITION BY Customer_ID) cnt,
ROW_NUMBER() OVER (PARTITION BY Customer_ID ORDER BY Order_Date) rn_first,
ROW_NUMBER() OVER (PARTITION BY Customer_ID ORDER BY Order_Date DESC) rn_last
FROM Orders
)
SELECT
Customer_ID,
MAX(CASE WHEN rn_first = 1 THEN Product_ID END) AS Product_ID_first,
MAX(CASE WHEN rn_last = 1 THEN Product_ID END) AS Product_ID_last
FROM cte
WHERE cnt >= 2
GROUP BY
Customer_ID
ORDER BY
Customer_ID;
答案 2 :(得分:1)
不幸的是,SQL Server还不支持将“第一”和“最后”功能用作聚合功能。它确实支持它们作为窗口功能,因此您可以:
select distinct customer_id,
first_value(product_id) over (partition by customer_id order by order_date asc) as first_product,
first_value(product_id) over (partition by customer_id order by order_date desc) as last_product
from orders o
where exists (select 1
from orders o2
where o2.customer_id = o.customer_id and
o2.order_date <> o.order_date
);
或者,如果您喜欢窗口功能,则可以省去select distinct
和exists
:
select customer_id, first_product, last_product
from (select o.*,
first_value(product_id) over (partition by customer_id order by order_date asc) as first_product,
first_value(product_id) over (partition by customer_id order by order_date desc) as last_product,
count(*) over (partition by customer_id) as cnt,
row_number() over (partition by customer_id order by order_date) as seqnum
) o
where cnt >= 2 and seqnum = 1;
我将条件聚合的措辞表达为:
select o.customer_id,
max(case when seqnum_asc = 1 then o.product_id end) as first_product,
max(case when seqnum_desc = 1 then o.product_id end) as last_product
from (select o.*,
row_number() over (partition by customer_id order by order_date asc) as seqnum_asc,
row_number() over (partition by customer_id order by order_date desc) as seqnum_desc
from orders o
) o
group by customer_id
having count(*) >= 2;
传统的非窗口函数方法将使用两个联接:
select o.customer_id,
firsto.product_id as first_product,
lasto.product_id as last_product
from (select customer_id, min(order_date) as min_od,
max(order_date) as max_od
from orders o
group by customer_id
having count(*) >= 2
) o join
orders firsto
on firsto.customer_id = o.customer_id and
firsto.order_date = o.min_od join
orders lasto
on lasto.customer_id = o.customer_id and
last.order_date = o.max_od;
如果您想从每个订单中获取多个值,这实际上是最方便的方法-除了产品外,还说金额,付款方式和日期。