是否可以获得组中前 X% 项目的平均值?
例如:
我有一个包含 item_id、timestamp 和 price 列的表。输出应按 item_id 和时间戳分组,“价格列”应取平均值。对于平均而言,应仅使用该组中最低的 X% 价格。
我发现了类似的问题(如何为每个组选择前 x 条记录),但这不适用于 sqlite。
是否可以获得组中前 X% 项目的平均值?
例如:
我有一个包含 item_id、timestamp 和 price 列的表。输出应按 item_id 和时间戳分组,“价格列”应取平均值。对于平均而言,应仅使用该组中最低的 X% 价格。
我发现了类似的问题(如何为每个组选择前 x 条记录),但这不适用于 sqlite。
获取每组中的前 n 条记录需要计数。假设没有重复项,以下查询返回项目的记录数:
select t.*,
(select count(*) from t t2 where t2.item_id = t.item_id
) as NumPrices
from t
这称为相关子查询。现在,让我们扩展这个想法以包括排名,然后计算正确组的平均值:
select item_id, avg(price)
from (select t.*,
(select count(*) from t t2 where t2.item_id = t.item_id
) as NumPrices,
(select count(*) from t t2 where t2.item_id = t.item_id and t2.price <= t.price
) as PriceRank
from t
) t
where (100.0*PriceRank / NumPrices) <= X
group by item_id
为了提高性能,您需要在(item_id, price)
.
要获取具有 IDI
和时间戳的组中的记录计数T
,请使用以下查询:
SELECT COUNT(*)
FROM MyTable
WHERE item_id = I
AND timestamp = T
要获得限制,请与 相乘X
,然后使用ROUND
/CAST
转换为整数:
SELECT CAST(ROUND(COUNT(*) * X / 100) AS INTEGER)
FROM MyTable
WHERE item_id = I
AND timestamp = T
要获取特定组中在该限制内的所有记录,请按价格对组中的记录进行排序,并限制返回的计数:
SELECT *
FROM MyTable
WHERE item_id = I
AND timestamp = T
ORDER BY price
LIMIT (SELECT CAST(ROUND(COUNT(*) * X / 100) AS INTEGER)
FROM MyTable
WHERE item_id = I
AND timestamp = T)
从理论上讲,要获得组平均值,请添加GROUP BY
以下内容:
SELECT item_id,
timestamp,
(SELECT AVG(price)
FROM (SELECT price
FROM MyTable T2
WHERE T2.item_id = T1.item_id
AND T2.timestamp = T1.timestamp
ORDER BY price
LIMIT (SELECT CAST(ROUND(COUNT(*) * X / 100) AS INTEGER)
FROM MyTable T3
WHERE T3.item_id = T1.item_id
AND T3.timestamp = T1.timestamp)
)
) AS AvgPriceLowestX
FROM MyTable T1
GROUP BY item_id,
timestamp
但是,SQLite 似乎不允许从LIMIT
子句内部访问相关变量,因此这在实践中不起作用。您必须获取所有组的 ID ( SELECT DISTINCT item_id, timestamp FROM MyTable
) 并为每个组执行上面的第三个查询。
在任何情况下,请确保您在三列item_id
、timestamp
、 和上都有一个索引,price
以获得良好的性能。