目录
-
- 摘要
- 一、排名计算概述
-
- [1.1 排名场景](#1.1 排名场景)
- [1.2 排名类型](#1.2 排名类型)
- [1.3 排名函数](#1.3 排名函数)
- 二、排名函数
-
- [2.1 基本排名](#2.1 基本排名)
- [2.2 分组排名](#2.2 分组排名)
- [2.3 百分位排名](#2.3 百分位排名)
- 三、Top-N计算
-
- [3.1 Top-N查询](#3.1 Top-N查询)
- [3.2 分组Top-N](#3.2 分组Top-N)
- [3.3 实时Top-N](#3.3 实时Top-N)
- 四、动态排序
-
- [4.1 实时排序](#4.1 实时排序)
- [4.2 多字段排序](#4.2 多字段排序)
- [4.3 动态排名更新](#4.3 动态排名更新)
- 五、排名变化追踪
-
- [5.1 排名变化检测](#5.1 排名变化检测)
- [5.2 排名历史](#5.2 排名历史)
- [5.3 排名趋势](#5.3 排名趋势)
- 六、多维度排名
-
- [6.1 多指标排名](#6.1 多指标排名)
- [6.2 分组多维度排名](#6.2 分组多维度排名)
- [6.3 时间窗口排名](#6.3 时间窗口排名)
- 七、实战案例
-
- [7.1 完整实时排名系统](#7.1 完整实时排名系统)
- 八、总结
- 参考资料
摘要
本文深入讲解DolphinDB实时排名计算技术。从排名函数到Top-N计算,从实时排行到动态排序,从多维度排名到排名变化追踪,全面介绍实时排名计算的核心方法。通过丰富的代码示例,帮助读者掌握Top-N实时排行的核心技能。
一、排名计算概述
1.1 排名场景
#mermaid-svg-zXoZtoSHgzfXM2ii{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-zXoZtoSHgzfXM2ii .error-icon{fill:#552222;}#mermaid-svg-zXoZtoSHgzfXM2ii .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-zXoZtoSHgzfXM2ii .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-zXoZtoSHgzfXM2ii .marker{fill:#333333;stroke:#333333;}#mermaid-svg-zXoZtoSHgzfXM2ii .marker.cross{stroke:#333333;}#mermaid-svg-zXoZtoSHgzfXM2ii svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-zXoZtoSHgzfXM2ii p{margin:0;}#mermaid-svg-zXoZtoSHgzfXM2ii .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-zXoZtoSHgzfXM2ii .cluster-label text{fill:#333;}#mermaid-svg-zXoZtoSHgzfXM2ii .cluster-label span{color:#333;}#mermaid-svg-zXoZtoSHgzfXM2ii .cluster-label span p{background-color:transparent;}#mermaid-svg-zXoZtoSHgzfXM2ii .label text,#mermaid-svg-zXoZtoSHgzfXM2ii span{fill:#333;color:#333;}#mermaid-svg-zXoZtoSHgzfXM2ii .node rect,#mermaid-svg-zXoZtoSHgzfXM2ii .node circle,#mermaid-svg-zXoZtoSHgzfXM2ii .node ellipse,#mermaid-svg-zXoZtoSHgzfXM2ii .node polygon,#mermaid-svg-zXoZtoSHgzfXM2ii .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-zXoZtoSHgzfXM2ii .rough-node .label text,#mermaid-svg-zXoZtoSHgzfXM2ii .node .label text,#mermaid-svg-zXoZtoSHgzfXM2ii .image-shape .label,#mermaid-svg-zXoZtoSHgzfXM2ii .icon-shape .label{text-anchor:middle;}#mermaid-svg-zXoZtoSHgzfXM2ii .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-zXoZtoSHgzfXM2ii .rough-node .label,#mermaid-svg-zXoZtoSHgzfXM2ii .node .label,#mermaid-svg-zXoZtoSHgzfXM2ii .image-shape .label,#mermaid-svg-zXoZtoSHgzfXM2ii .icon-shape .label{text-align:center;}#mermaid-svg-zXoZtoSHgzfXM2ii .node.clickable{cursor:pointer;}#mermaid-svg-zXoZtoSHgzfXM2ii .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-zXoZtoSHgzfXM2ii .arrowheadPath{fill:#333333;}#mermaid-svg-zXoZtoSHgzfXM2ii .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-zXoZtoSHgzfXM2ii .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-zXoZtoSHgzfXM2ii .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zXoZtoSHgzfXM2ii .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-zXoZtoSHgzfXM2ii .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zXoZtoSHgzfXM2ii .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-zXoZtoSHgzfXM2ii .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-zXoZtoSHgzfXM2ii .cluster text{fill:#333;}#mermaid-svg-zXoZtoSHgzfXM2ii .cluster span{color:#333;}#mermaid-svg-zXoZtoSHgzfXM2ii div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-zXoZtoSHgzfXM2ii .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-zXoZtoSHgzfXM2ii rect.text{fill:none;stroke-width:0;}#mermaid-svg-zXoZtoSHgzfXM2ii .icon-shape,#mermaid-svg-zXoZtoSHgzfXM2ii .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-zXoZtoSHgzfXM2ii .icon-shape p,#mermaid-svg-zXoZtoSHgzfXM2ii .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-zXoZtoSHgzfXM2ii .icon-shape .label rect,#mermaid-svg-zXoZtoSHgzfXM2ii .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-zXoZtoSHgzfXM2ii .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-zXoZtoSHgzfXM2ii .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-zXoZtoSHgzfXM2ii :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;} 排名应用
设备排名
排名结果
产品排名
区域排名
1.2 排名类型
| 类型 | 说明 |
|---|---|
| Top-N | 前N名 |
| Bottom-N | 后N名 |
| 百分位排名 | 百分比排名 |
| 分组排名 | 分组内排名 |
1.3 排名函数
| 函数 | 说明 |
|---|---|
| rank | 排名(有间隙) |
| dense_rank | 排名(无间隙) |
| row_number | 行号 |
| percent_rank | 百分比排名 |
二、排名函数
2.1 基本排名
python
// 基本排名
def basicRank(data, valueCol) {
return select *, rank() over (order by eval(valueCol) desc) as rank
from data
}
// 紧凑排名
def denseRank(data, valueCol) {
return select *, dense_rank() over (order by eval(valueCol) desc) as rank
from data
}
// 行号
def rowNumber(data, orderCol) {
return select *, row_number() over (order by eval(orderCol)) as row_num
from data
}
2.2 分组排名
python
// 分组排名
def groupRank(data, groupCol, valueCol) {
return select *,
rank() over (partition by eval(groupCol) order by eval(valueCol) desc) as rank
from data
}
// 使用示例
t = table(
["A", "A", "A", "B", "B", "B"] as group,
[100, 90, 80, 95, 85, 75] as value
)
result = groupRank(t, `group, `value)
2.3 百分位排名
python
// 百分位排名
def percentRank(data, valueCol) {
return select *,
percent_rank() over (order by eval(valueCol)) as pct_rank
from data
}
三、Top-N计算
3.1 Top-N查询
python
// Top-N查询
def topN(data, valueCol, n = 10) {
return select top n *
from data
order by eval(valueCol) desc
}
// Bottom-N查询
def bottomN(data, valueCol, n = 10) {
return select top n *
from data
order by eval(valueCol)
}
3.2 分组Top-N
python
// 分组Top-N
def groupTopN(data, groupCol, valueCol, n = 5) {
return select * from (
select *,
rank() over (partition by eval(groupCol) order by eval(valueCol) desc) as rank
from data
) where rank <= n
}
3.3 实时Top-N
python
// 实时Top-N计算
share table(1:0,
`device_id`temperature`rank,
[SYMBOL, DOUBLE, INT]) as top_n_result
def calculateRealtimeTopN() {
// 获取最新数据
data = select device_id, last(temperature) as temperature
from sensor_stream
where timestamp > now() - 60000
group by device_id
// 计算排名
ranked = select *, rank() over (order by temperature desc) as rank
from data
// 取Top 10
top10 = select top 10 * from ranked order by rank
// 更新结果
truncate(top_n_result)
top_n_result.append!(top10)
}
四、动态排序
4.1 实时排序
python
// 实时排序
def realtimeSort(data, sortCol, order = "desc") {
if (order == "desc") {
return select * from data order by eval(sortCol) desc
} else {
return select * from data order by eval(sortCol)
}
}
4.2 多字段排序
python
// 多字段排序
def multiColumnSort(data, sortCols, orders) {
// 构建排序语句
orderBy = ""
for (i in 0..sortCols.size()) {
if (i > 0) {
orderBy += ", "
}
orderBy += sortCols[i] + " " + orders[i]
}
return select * from data order by eval(orderBy)
}
4.3 动态排名更新
python
// 动态排名更新
share table(1:0,
`device_id`value`rank`update_time,
[SYMBOL, DOUBLE, INT, TIMESTAMP]) as dynamic_rank
def updateDynamicRank() {
while (true) {
// 获取最新值
data = select device_id, last(temperature) as value
from sensor_stream
where timestamp > now() - 60000
group by device_id
// 计算排名
ranked = select device_id, value,
rank() over (order by value desc) as rank,
now() as update_time
from data
// 更新
truncate(dynamic_rank)
dynamic_rank.append!(ranked)
sleep(5000)
}
}
submitJob("dynamic_rank", "动态排名", updateDynamicRank)
五、排名变化追踪
5.1 排名变化检测
python
// 排名变化表
share table(1:0,
`device_id`old_rank`new_rank`change`change_time,
[SYMBOL, INT, INT, INT, TIMESTAMP]) as rank_change
// 检测排名变化
def detectRankChange(oldRank, newRank) {
for (deviceId in oldRank.device_id) {
oldPos = exec rank from oldRank where device_id = deviceId
newPos = exec rank from newRank where device_id = deviceId
if (oldPos.size() > 0 and newPos.size() > 0) {
if (oldPos[0] != newPos[0]) {
insert into rank_change values (
deviceId, oldPos[0], newPos[0], newPos[0] - oldPos[0], now()
)
}
}
}
}
5.2 排名历史
python
// 排名历史表
share table(1:0,
`record_time`device_id`value`rank,
[TIMESTAMP, SYMBOL, DOUBLE, INT]) as rank_history
// 记录排名历史
def recordRankHistory(ranked) {
for (row in ranked) {
insert into rank_history values (now(), row.device_id, row.value, row.rank)
}
}
5.3 排名趋势
python
// 排名趋势分析
def rankTrend(deviceId, periods = 10) {
return select record_time, rank
from rank_history
where device_id = deviceId
order by record_time desc
limit periods
}
六、多维度排名
6.1 多指标排名
python
// 多指标排名
def multiMetricRank(data, metrics, weights) {
// 计算综合得分
score = 0
for (i in 0..metrics.size()) {
score += data[metrics[i]] * weights[i]
}
data[`score] = score
return select *, rank() over (order by score desc) as rank
from data
}
6.2 分组多维度排名
python
// 分组多维度排名
def groupMultiMetricRank(data, groupCol, metrics, weights) {
// 计算综合得分
score = 0
for (i in 0..metrics.size()) {
// 归一化
maxVal = max(data[metrics[i]])
minVal = min(data[metrics[i]])
normalized = (data[metrics[i]] - minVal) / (maxVal - minVal)
score += normalized * weights[i]
}
data[`score] = score
return select *,
rank() over (partition by eval(groupCol) order by score desc) as rank
from data
}
6.3 时间窗口排名
python
// 时间窗口排名
def timeWindowRank(data, timeWindow = 3600000) {
return select device_id,
bar(timestamp, timeWindow) as window,
avg(temperature) as avg_temp,
rank() over (partition by bar(timestamp, timeWindow)
order by avg(temperature) desc) as rank
from data
group by device_id, bar(timestamp, timeWindow)
}
七、实战案例
7.1 完整实时排名系统
python
// ========== 实时排名计算系统 ==========
// 1. 创建数据流
share streamTable(100000:0,
`device_id`timestamp`temperature`humidity`pressure,
[SYMBOL, TIMESTAMP, DOUBLE, DOUBLE, DOUBLE]) as sensor_stream
enableTablePersistence(sensor_stream, true, true, 1000000)
// 2. 创建排名结果表
share table(1:0,
`device_id`temperature`rank`update_time,
[SYMBOL, DOUBLE, INT, TIMESTAMP]) as temperature_rank
share table(1:0,
`device_id`humidity`rank`update_time,
[SYMBOL, DOUBLE, INT, TIMESTAMP]) as humidity_rank
// 3. 排名计算任务
def rankTask() {
while (true) {
now = now()
// 获取最新数据
data = select device_id,
last(temperature) as temperature,
last(humidity) as humidity
from sensor_stream
where timestamp > now - 60000
group by device_id
if (data.rows() > 0) {
// 温度排名
tempRank = select device_id, temperature,
rank() over (order by temperature desc) as rank,
now as update_time
from data
truncate(temperature_rank)
temperature_rank.append!(tempRank)
// 湿度排名
humidRank = select device_id, humidity,
rank() over (order by humidity desc) as rank,
now as update_time
from data
truncate(humidity_rank)
humidity_rank.append!(humidRank)
}
sleep(5000)
}
}
submitJob("rank_task", "排名计算", rankTask)
// 4. Top-N接口
def getTopDevices(metric, n = 10) {
if (metric == "temperature") {
return select top n * from temperature_rank order by rank
} else if (metric == "humidity") {
return select top n * from humidity_rank order by rank
}
return null
}
addFunctionView(getTopDevices)
// 5. 模拟数据
def generateMockData() {
while (true) {
data = table(
take(1..20, 20) as device_id,
take(now(), 20) as timestamp,
rand(20.0..40.0, 20) as temperature,
rand(40.0..80.0, 20) as humidity,
rand(1000.0..1020.0, 20) as pressure
)
sensor_stream.append!(data)
sleep(5000)
}
}
submitJob("mock_data", "模拟数据", generateMockData)
print("实时排名计算系统启动完成")
八、总结
本文详细介绍了DolphinDB实时排名计算:
- 排名函数:rank、dense_rank、row_number、percent_rank
- Top-N计算:Top-N查询、分组Top-N、实时Top-N
- 动态排序:实时排序、多字段排序、动态更新
- 排名追踪:变化检测、排名历史、排名趋势
- 多维度排名:多指标排名、分组排名、时间窗口排名
思考题:
- 如何处理排名相同的情况?
- 如何优化大规模数据的排名计算?
- 如何实现排名的实时推送?