sql - 递归 ORDER BY
问题描述
我有一个USERS
表格,它是一个成员矩阵,如下所示。表在 上是唯一的ID
,每个都ID
属于至少一个组,但可以属于所有 3 个。
SELECT 1 AS ID, 0 AS IS_A, 0 AS IS_B, 1 AS IS_C FROM DUAL UNION ALL
SELECT 2,0,1,0 FROM DUAL UNION ALL
SELECT 3,0,1,1 FROM DUAL UNION ALL
SELECT 4,1,1,0 FROM DUAL UNION ALL
SELECT 5,1,1,0 FROM DUAL UNION ALL
SELECT 6,1,1,1 FROM DUAL UNION ALL
SELECT 7,0,1,1 FROM DUAL UNION ALL
SELECT 8,0,0,1 FROM DUAL UNION ALL
SELECT 9,1,0,0 FROM DUAL UNION ALL
SELECT 10,1,0,1 FROM DUAL UNION ALL
SELECT 11,0,0,1 FROM DUAL UNION ALL
SELECT 12,0,1,1 FROM DUAL
最终目标是SELECT
随机抽取来自 A 的至少 4 个用户、来自 B 的 3 个用户和来自 C 的 5 个用户的样本(只是一个例子),但恰好有 10 个不同ID
的 s(否则解决方案是微不足道的;只是SELECT *
)。
重点不是确定是否有可能,而是更多地尝试尽最大努力最大化会员资格。
输出预计在 上是唯一的ID
。
我只能想到一种程序方法来实现这一点:
- 拿第
ID
一个MAX(IS_A+IS_B+IS_C)
- 检查是否达到配额
- 例如,如果我们已经有来自 A 的 4 个用户,那么我们将继续使用下一个 ID ,完全忽略列中的
MAX(IS_B+IS_C)
任何进一步贡献IS_A
- 如果我们已经完成了所有配额,则恢复
MAX(IS_A+IS_B+IS_C)
为获取“奖励”积分 - 达到总最大值 10 时停止
本质上,我们优先考虑并逐步采用ID
未达到配额的组中成员最多的组
但是,我无法弄清楚如何在 Oracle SQL 中执行此操作,因为这ORDER BY
不仅取决于当前行的值,而且还递归地取决于先前的行是否已填满相应的配额。
我试过ROWNUM
, ROW_NUMBER()
, SUM(IS_A) OVER (ORDER BY ...)
,RECURSIVE CTE
但无济于事。我最好的是
WITH CTE AS (
SELECT ID, IS_A, IS_B, IS_C
, ROW_NUMBER() OVER (ORDER BY IS_A+IS_B+IS_C DESC) AS RN
FROM USERS
)
, CTE2 AS (
SELECT CTE.*
, GREATEST(4 - SUM(IS_A) OVER (ORDER BY RN), 0.001) AS QUOTA_A --clip negatives to 0.001
, GREATEST(3 - SUM(IS_B) OVER (ORDER BY RN), 0.001) AS QUOTA_B --so that when all quotas are exhausted,
, GREATEST(5 - SUM(IS_C) OVER (ORDER BY RN), 0.001) AS QUOTA_C --we still prioritize those that contribute most number of concurrent memberships
FROM CTE
)
SELECT ID FROM CTE2
ORDER BY QUOTA_A*IS_A + QUOTA_B*IS_B + QUOTA_C*IS_C DESC
FETCH NEXT 10 ROWS ONLY
但它不起作用,因为它QUOTA_A
是基于ORDER BY RN
而不是递归计算的。
提前致谢!
解决方案
推荐阅读
- excel - 使用 Selenium VBA 从网页复制表格
- javascript - 没有调用快速路线
- python - Python Bot按顺序发送消息
- etl - 表格设计:周转时间的转化率
- php - Laravel 使用自定义 php.ini 和 artisan serve
- html - HTML 不想在第二个 html 文件中加载 CSS
- google-apps-script - Google 电子表格 - 查找所有隐藏的行 - 仅包括未隐藏的行
- javascript - 根据javascript中另一个字段中的条件对字段值求和
- char - 忽略未知长度的数据输入中的非整数
- sql - 即使在控制文件中有 SQL 函数,我也可以使用直接加载吗?