我正在尝试为由一列 (package_id) 链接但另一列 (package_item_id) 不匹配的行的所有可能组合生成聚合结果。
我有一个派生表包:
package_id | package_item_id | 数量 | variant_id | 零售价 | 销售价格 | 有库存 |
---|---|---|---|---|---|---|
1000001 | 28 | 1 | 3399 | 489.00 | 342.30 | 26 |
1000001 | 28 | 1 | 3400 | 489.00 | 342.30 | 23 |
1000001 | 28 | 1 | 3409 | 489.00 | 342.30 | 81 |
1000001 | 29 | 1 | 821 | 44.95 | 35.95 | 741 |
1000001 | 30 | 1 | 807 | 39.95 | 31.95 | 162 |
1000002 | 31 | 1 | 6369 | 519.00 | 363.30 | 93 |
1000002 | 31 | 1 | 6371 | 519.00 | 363.30 | 60 |
1000002 | 31 | 1 | 6372 | 519.00 | 363.30 | 40 |
1000002 | 31 | 1 | 19289 | 519.00 | 363.30 | 24 |
1000002 | 31 | 1 | 19290 | 519.00 | 363.30 | 20 |
1000002 | 31 | 1 | 21774 | 519.00 | 363.30 | 14 |
1000002 | 31 | 1 | 23045 | 519.00 | 363.30 | 0 |
1000002 | 37 | 1 | 821 | 44.95 | 35.95 | 741 |
1000002 | 38 | 1 | 807 | 39.95 | 31.95 | 162 |
此结构支持零售网站的打包交易系统:
package_id 与一组可以作为包购买的元素相关。
package_item_id 分解了子元素(根据包的不同,数量也不同),用户可以从中选择variant_ids。
即包装:高级山地自行车,包装物品:车架,款式:蓝色、红色、黄色,包装物品:车轮,款式:窄、宽,包装物品:车座,款式:标准
我正在尝试生成一个聚合 package_id 的每个潜在组合的结果。将 package_id 和variants_ids 连接到查询字符串中并计算分组项目的总价格。数量列决定了为 package_item_id 提供的数量,因此是价格的乘数。此外,我想检查每个变体是否有足够的库存来组成包装 true (1) 或 false (0)
我试图仅针对第一个 package_id 实现的结果示例:
package_id | 查询字符串 | 零售价 | 销售价格 | 库存 |
---|---|---|---|---|
1000001 |
|
598.9 | 430.2 | 1 |
1000001 |
|
598.9 | 430.2 | 1 |
1000001 |
|
598.9 | 430.2 | 1 |
1000001 |
|
573.9 | 410.2 | 1 |
1000001 |
|
573.9 | 410.2 | 1 |
1000001 |
|
573.9 | 410.2 | 1 |
我一直在尝试在组合递归 CTE 中使用窗口函数来在组合 ID 下创建所有不同的组合,我希望它们能够获得我需要的聚合结果,但到目前为止我无法实现我的目标。
WITH RECURSIVE cte_packages AS (
SELECT
package_id,
DENSE_RANK() OVER (ORDER BY package_id) AS p_group,
package_item_id,
DENSE_RANK() OVER (PARTITION BY package_id ORDER BY package_item_id) AS pi_group,
ROW_NUMBER() OVER (PARTITION BY package_item_id ORDER BY variant_id) AS pi_group_row,
COUNT(*) OVER (PARTITION BY package_item_id) AS pi_group_row_count,
quantity,
variant_id,
retail_price,
sell_price,
stock_available
FROM packages
),
cte_combinations AS
(
SELECT
0 AS combination_id,
p_group,
p_group AS next_p_group,
pi_group,
pi_group_row,
CASE
WHEN pi_group_row < pi_group_row_count
THEN pi_group_row + 1
ELSE 1
END
AS next_pi_group_row,
pi_group_row_count,
package_id,
package_item_id,
quantity,
variant_id,
retail_price,
sell_price,
stock_available
FROM
cte_packages
WHERE
p_group = 1 AND pi_group = 1 AND pi_group_row = 1
UNION
SELECT
cc.combination_id + 1,
cpi.p_group,
CASE
WHEN cpi.pi_group_row = cpi.pi_group_row_count
THEN cpi.p_group + 1
ELSE cpi.p_group
END
AS next_p_group,
cpi.pi_group,
cpi.pi_group_row,
CASE
WHEN cpi.pi_group_row < cpi.pi_group_row_count
THEN cpi.pi_group_row + 1
ELSE 1
END
AS next_pi_group_row,
cpi.pi_group_row_count,
cpi.package_id,
cpi.package_item_id,
cpi.quantity,
cpi.variant_id,
cpi.retail_price,
cpi.sell_price,
cpi.stock_available
FROM
cte_combinations cc
INNER JOIN
cte_packages cpi
ON cpi.p_group = cc.next_p_group AND cpi.pi_group = 1 AND cpi.pi_group_row = cc.next_pi_group_row
LEFT JOIN
cte_packages opi
ON opi.p_group = cpi.p_group AND opi.pi_group <> 1
)
SELECT * FROM cte_combinations
我不确定我是否正确地实现了这个目标,或者我想要实现的目标是否可能。
DB Fiddle 链接如下:
AFAICT 我们需要为每个
variant_id
生成 package_id
的所有可能组合。由于 package_item_id
的数量不同,这将涉及每个 package_item_id
的自连接。然而,对于不同数量的项目,通常需要动态数量的联接,而 SQL 本身并不支持这一点。
此代码片段可能会实现您正在寻找的结果,但仅每个
package_item_id
有三个
package_id
值
SELECT
p1.package_id,
CONCAT('p_id=', p1.package_id, '&v_id=', p1.variant_id,
'&v_id=', p2.variant_id, '&v_id=', p3.variant_id) AS querystring,
(p1.quantity * p1.retail_price + p2.quantity * p2.retail_price + p3.quantity * p3.retail_price) AS total_retail_price,
(p1.quantity * p1.sell_price + p2.quantity * p2.sell_price + p3.quantity * p3.sell_price) AS total_sell_price,
CASE
WHEN p1.stock_available >= p1.quantity AND p2.stock_available >= p2.quantity AND p3.stock_available >= p3.quantity
THEN 1
ELSE 0
END AS stock_available
FROM packages p1
JOIN packages p2 ON p1.package_id = p2.package_id AND p1.package_item_id <> p2.package_item_id
JOIN packages p3 ON p1.package_id = p3.package_id AND p1.package_item_id <> p3.package_item_id AND p2.package_item_id <> p3.package_item_id
GROUP BY p1.package_id, p1.variant_id, p2.variant_id, p3.variant_id;