You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PostgreSQL中如何获取行内值相对位置,判断商品购买先后

问题描述

我正在使用PostgreSQL中的orders表,表结构及数据如下:

user_id   product       order_date
1         pants         7/1/2022
2         shirt         6/1/2022
1         socks         3/17/2023
3         pants         2/17/2023
4         shirt         3/13/2023
2         pants         8/15/2022
1         hat           4/15/2022
5         hat           3/14/2023
2         socks         12/3/2022
3         shirt         4/15/2023
4         socks         1/15/2023
4         pants         4/19/2023
5         shirt         5/2/2023
5         belt          5/15/2023

我已经生成了展示客户订单序列的表:

user_id   first_order   second_order    third_order
1         hat           pants           socks
2         shirt         pants           socks
3         pants         shirt           <null>
4         socks         shirt           pants
5         hat           shirt           belt            

现在需要在行级别添加指示器shirt_before_pants,判断特定客户是否先购买shirt再购买pants,期望输出如下:

user_id   first_order   second_order    third_order     shirt_before_pants
1         hat           pants           socks           false
2         shirt         pants           socks           true
3         pants         shirt           <null>          false
4         socks         shirt           pants           true
5         hat           shirt           belt            false

请问能否获取行内给定值的相对位置?

解决方案

当然可以获取行内给定值的相对位置,以下是两种实用的解决方法:

方法1:基于已生成的订单序列表处理

通过字符串拼接结合POSITION函数判断两个商品的位置先后,同时处理商品不存在的情况:

SELECT 
    user_id,
    first_order,
    second_order,
    third_order,
    CASE 
        -- 仅当两个商品都存在时,判断shirt的位置是否在pants之前
        WHEN 'shirt' IN (first_order, second_order, third_order) 
             AND 'pants' IN (first_order, second_order, third_order)
             AND POSITION('shirt' IN CONCAT_WS(',', first_order, second_order, third_order)) 
                < POSITION('pants' IN CONCAT_WS(',', first_order, second_order, third_order))
        THEN true
        ELSE false
    END AS shirt_before_pants
FROM 你的订单序列表名;

方法2:直接从原orders表计算(更灵活)

如果后续存在更多订单,预先生成的序列表列数可能不足,直接从原表按用户分组计算订单顺序更可靠:

WITH user_order_ranks AS (
    SELECT 
        user_id,
        product,
        -- 按用户分组,根据订单日期生成每个商品的购买顺序排名
        ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY order_date) AS order_rank
    FROM orders
)
SELECT 
    u1.user_id,
    -- 提取各顺序对应的商品
    MAX(CASE WHEN u1.order_rank = 1 THEN u1.product END) AS first_order,
    MAX(CASE WHEN u1.order_rank = 2 THEN u1.product END) AS second_order,
    MAX(CASE WHEN u1.order_rank = 3 THEN u1.product END) AS third_order,
    -- 判断shirt的购买排名是否早于pants
    CASE 
        WHEN MAX(CASE WHEN u1.product = 'shirt' THEN u1.order_rank END) 
             < MAX(CASE WHEN u1.product = 'pants' THEN u1.order_rank END)
        THEN true
        ELSE false
    END AS shirt_before_pants
FROM user_order_ranks u1
GROUP BY u1.user_id
ORDER BY u1.user_id;

这种方法无需依赖预先生成的序列表,能自动适配任意数量的订单,同时精准判断两个商品的购买顺序。

内容的提问来源于stack exchange,提问作者crimson

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 11:30:38