我正在尝试构建一个sql查询,该查询将返回一个包含总和的ID列表,该总和小于使用最少项目数的给定值的OR。
以下是我将要查询的表的示例。
ID Value
-----------
226 2.3
331 3.1
25 1.5
28 1.5
29 1.2
52 5.2
38 3.5
此处按值asc。
排序ID Value
----------
29 1.2
25 1.5
28 1.5
226 2.3
331 3.1
38 3.5
52 5.2
示例A:
如果我的值为6,我希望查询返回ID 29,25,28和226。 1.2 + 1.5 + 1.5 + 2.3 = 6.5
例B:
如果我的值为19,我希望查询返回所有ID(29,25,28,226,331,38,52)。
1.2 + 1.5 + 1.5 + 2.3 + 3.1 + 3.5 + 5.2 = 18.3
我尝试过这里建议的答案: SQL select elements where sum of field is less than N
然而,这并没有完全满足我的需要,因为它只返回加起来比设定值少的ID。还假设ID是递增的,而当我按asc值排序时则不是这种情况。
这是否可以在sql语句中使用?或者我是否必须执行一个程序/功能来完成这项任务?
答案 0 :(得分:0)
假设您正在按升序说出这些值,而您希望在最接近所需总数时停止:
Oracle 11g R2架构设置:
CREATE TABLE data ( ID, Value ) AS
SELECT 226, 2.3 FROM DUAL
UNION ALL SELECT 331, 3.1 FROM DUAL
UNION ALL SELECT 25, 1.5 FROM DUAL
UNION ALL SELECT 28, 1.5 FROM DUAL
UNION ALL SELECT 29, 1.2 FROM DUAL
UNION ALL SELECT 52, 5.2 FROM DUAL
UNION ALL SELECT 38, 3.5 FROM DUAL;
查询1 :
WITH differences AS (
SELECT ID,
Value,
ABS(
SUM( Value ) OVER ( ORDER BY Value ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW )
- 6 -- REPLACE THIS WITH :desired_total
) AS difference
FROM data
),
min_difference AS (
SELECT MIN( Value ) KEEP ( DENSE_RANK FIRST ORDER BY difference ASC ) AS max_value,
MIN( ID ) KEEP ( DENSE_RANK FIRST ORDER BY difference ASC ) AS max_id
FROM differences
)
SELECT ID,
Value
FROM differences d
INNER JOIN
min_difference m
ON ( d.value < max_value
OR ( d.value = m.max_value AND d.id <= max_id ) )
<强> Results 强>:
| ID | VALUE |
|-----|-------|
| 226 | 2.3 |
| 25 | 1.5 |
| 28 | 1.5 |
| 29 | 1.2 |
编辑 - 运行总计时停止只是大于或等于所需总数
查询1 :
计算每一行的运行总数(按升序排列)然后选择运行总数小于所需总数的所有行以及下一行(总计的最小运行总数大于或等于到期望的总数。)
WITH running_totals AS (
SELECT ID,
Value,
SUM( Value ) OVER ( ORDER BY Value ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS running_total
FROM data
)
SELECT ID,
Value
FROM running_totals
WHERE running_total < 6
UNION ALL
SELECT MIN( id ) KEEP ( DENSE_RANK FIRST ORDER BY running_total ),
MIN( value ) KEEP ( DENSE_RANK FIRST ORDER BY running_total )
FROM running_totals
WHERE running_total >= 6
<强> Results 强>:
| ID | VALUE |
|-----|-------|
| 29 | 1.2 |
| 28 | 1.5 |
| 25 | 1.5 |
| 226 | 2.3 |
编辑2 - 另一种方法:
WITH running_totals AS (
SELECT ID,
Value,
SUM( Value ) OVER ( ORDER BY Value, ID ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW ) AS running_total,
ROW_NUMBER() OVER ( ORDER BY Value, ID ) AS idx
FROM data
)
SELECT ID,
Value
FROM running_totals
WHERE idx <= (SELECT MAX(idx) + 1 FROM running_totals WHERE running_total < 6 );