DolphinDB实时排名计算:Top-N实时排行

目录

    • 摘要
    • 一、排名计算概述
      • [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实时排名计算:

  1. 排名函数:rank、dense_rank、row_number、percent_rank
  2. Top-N计算:Top-N查询、分组Top-N、实时Top-N
  3. 动态排序:实时排序、多字段排序、动态更新
  4. 排名追踪:变化检测、排名历史、排名趋势
  5. 多维度排名:多指标排名、分组排名、时间窗口排名

思考题

  1. 如何处理排名相同的情况?
  2. 如何优化大规模数据的排名计算?
  3. 如何实现排名的实时推送?

参考资料


相关推荐
cmes_love18 小时前
CME、LME、CBOT、NYMEX等交易所外盘期货tick和分钟历史行情数据下载和分析
数据库·区块链
大模型码小白18 小时前
向量化引擎与 AI 排障:当 SIMD 遇到异常检测,存储诊断的范式转移
java·大数据·数据库·人工智能·python
刘小八20 小时前
Redis 缓存一致性:一文讲透延时双删原理、并发时序
java·数据库·redis·缓存
糖果店的幽灵20 小时前
【langgraph 从入门到精通graphApi 篇】Command 与动态流程控制
android·java·数据库·人工智能·langgraph
数行拙笔20 小时前
Redis---zset类型
数据库·redis·缓存
老大白菜20 小时前
Omnigent(omni)使用说明
服务器·数据库·microsoft
数智化管理手记21 小时前
全面预算管理执行偏差大?全面预算管理全流程落地步骤是什么
大数据·网络·数据库·人工智能·数据挖掘
倔强的石头_21 小时前
SQL 语法全兼容,但结果就是不一样——国产化迁移里最难缠的九类隐患
数据库
kobe_OKOK_1 天前
django外键字段会自动在数据库字段后面加上_id
数据库·django·sqlite