admin管理员组

文章数量:1402995

I am using SeaORM in a Rust project and trying to retrieve ranked user balances using MySQL’s RANK() OVER (ORDER BY ...). However, the rank field always returns 0 for all rows.

Rust Code:

#[allow(unused_imports)]
use loco_rs::{cli::playground, prelude::*};
use myapp::app::App;

use myapp::models::_entities::wallets::{self, ActiveModel, Entity, Model};
use sea_orm::{DatabaseConnection, DbBackend, Statement, Value};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Debug)]
struct UserRank {
    name: String,
    rank: i64,
    balance: i32,
}

#[tokio::main]
async fn main() -> loco_rs::Result<()> {
    let _ctx = playground::<App>().await?;
    let db = &_ctx.db;

    let coins_query = r#"
        SELECT t.first_name, t.last_name, w.coins, 
               RANK() OVER (ORDER BY w.coins DESC) AS `rank`
        FROM wallets w
        JOIN game_users g ON w.game_user_id = g.id
        JOIN telegram_users t ON g.id = t.game_user_id
        ORDER BY w.coins DESC LIMIT 10;
    "#;

    let coins = db
        .query_all(Statement::from_string(DbBackend::MySql, coins_query))
        .await
        .unwrap()
        .into_iter()
        .map(|row| UserRank {
            name: format!(
                "{} {}",
                row.try_get::<String>("", "first_name").unwrap_or_default(),
                row.try_get::<String>("", "last_name").unwrap_or_default()
            ),
            rank: row.try_get::<i64>("", "rank").unwrap_or(0), // Always returns 0
            balance: row.try_get::<i32>("", "coins").unwrap_or(0),
        })
        .collect::<Vec<_>>();

    println!("User Ranks: {:#?}", coins);
    Ok(())
}

Output (Unexpected Behavior):

User Ranks: [
    UserRank {
        name: "Alok Alok",
        rank: 0,   // Should be 1
        balance: 1290,
    },
    UserRank {
        name: "Alok2 Alok2 ",
        rank: 0,   // Should be 2
        balance: 0,
    },
]

Things I Have Tried:

  1. Changing the rank field type from i32 to i64 in UserRank struct.
  2. Wrapping the alias in backticks: rank: row.try_get::<i64>("", "`rank`").unwrap_or(0),
  3. Running the query directly in MySQL (works fine, returns correct ranks).

Why is RANK() OVER (...) always returning 0 when retrieved using SeaORM, and how can I correctly fetch the computed rank column in Rust?

I am using SeaORM in a Rust project and trying to retrieve ranked user balances using MySQL’s RANK() OVER (ORDER BY ...). However, the rank field always returns 0 for all rows.

Rust Code:

#[allow(unused_imports)]
use loco_rs::{cli::playground, prelude::*};
use myapp::app::App;

use myapp::models::_entities::wallets::{self, ActiveModel, Entity, Model};
use sea_orm::{DatabaseConnection, DbBackend, Statement, Value};
use serde::{Deserialize, Serialize};

#[derive(Serialize, Debug)]
struct UserRank {
    name: String,
    rank: i64,
    balance: i32,
}

#[tokio::main]
async fn main() -> loco_rs::Result<()> {
    let _ctx = playground::<App>().await?;
    let db = &_ctx.db;

    let coins_query = r#"
        SELECT t.first_name, t.last_name, w.coins, 
               RANK() OVER (ORDER BY w.coins DESC) AS `rank`
        FROM wallets w
        JOIN game_users g ON w.game_user_id = g.id
        JOIN telegram_users t ON g.id = t.game_user_id
        ORDER BY w.coins DESC LIMIT 10;
    "#;

    let coins = db
        .query_all(Statement::from_string(DbBackend::MySql, coins_query))
        .await
        .unwrap()
        .into_iter()
        .map(|row| UserRank {
            name: format!(
                "{} {}",
                row.try_get::<String>("", "first_name").unwrap_or_default(),
                row.try_get::<String>("", "last_name").unwrap_or_default()
            ),
            rank: row.try_get::<i64>("", "rank").unwrap_or(0), // Always returns 0
            balance: row.try_get::<i32>("", "coins").unwrap_or(0),
        })
        .collect::<Vec<_>>();

    println!("User Ranks: {:#?}", coins);
    Ok(())
}

Output (Unexpected Behavior):

User Ranks: [
    UserRank {
        name: "Alok Alok",
        rank: 0,   // Should be 1
        balance: 1290,
    },
    UserRank {
        name: "Alok2 Alok2 ",
        rank: 0,   // Should be 2
        balance: 0,
    },
]

Things I Have Tried:

  1. Changing the rank field type from i32 to i64 in UserRank struct.
  2. Wrapping the alias in backticks: rank: row.try_get::<i64>("", "`rank`").unwrap_or(0),
  3. Running the query directly in MySQL (works fine, returns correct ranks).

Why is RANK() OVER (...) always returning 0 when retrieved using SeaORM, and how can I correctly fetch the computed rank column in Rust?

Share Improve this question edited Mar 21 at 11:33 Shadow 34.3k10 gold badges65 silver badges75 bronze badges asked Mar 21 at 10:32 AlokAlok 10.7k11 gold badges70 silver badges130 bronze badges
Add a comment  | 

1 Answer 1

Reset to default 0

The correct type for RANK() OVER (...) in MySQL when using SeaORM is u32 or u64. Changing the rank field to u32 or u64 resolves the issue and retrieves the correct values.

本文标签: rustRANK() Always Returns 0 in SeaORM QueryStack Overflow