我怎么选择(或某)的随机行(s)从表中使用SQLAlchemy?

有帮助吗?

解决方案

这在很大程度上是一个数据库特定的问题。

我知道,PostgreSQL源码,MySQL和Oracle的能力,以便通过一个随机的功能,因此可以使用这SQLAlchemy:

from  sqlalchemy.sql.expression import func, select

select.order_by(func.random()) # for PostgreSQL, SQLite

select.order_by(func.rand()) # for MySQL

select.order_by('dbms_random.value') # For Oracle

接下来,你需要限制查询数的记录你需要(例如使用 .limit()).

铭记,至少在PostgreSQL,随机选择的记录具有严重性能的问题; 在这里, 是篇好文章有关。

其他提示

如果您使用的对象和表不大(或者你有其量的行缓存)而你想要的数据库独立的真正简单的办法。

import random
rand = random.randrange(0, session.query(Table).count()) 
row = session.query(Table)[rand]

这是作弊略有但是这就是为什么你使用一个奥姆.

有一个简单的方法来拉的随机行为的数据库独立的。只是使用。偏().没有必要把所有行:

import random
query = DBSession.query(Table)
rowCount = int(query.count())
randomRow = query.offset(int(rowCount*random.random())).first()

其表是你的表(或者你可以把任何查询有).如果你想要一些行,然后你就可以运行这个时间,并确保每个行是不同于以前。

这四个不同的变化,从最慢的速度最快的。 timeit 结果在底层:

from sqlalchemy.sql import func
from sqlalchemy.orm import load_only

def simple_random():
    return random.choice(model_name.query.all())

def load_only_random():
    return random.choice(model_name.query.options(load_only('id')).all())

def order_by_random():
    return model_name.query.order_by(func.random()).first()

def optimized_random():
    return model_name.query.options(load_only('id')).offset(
            func.floor(
                func.random() *
                db.session.query(func.count(model_name.id))
            )
        ).limit(1).all()

timeit 结果为10,000个运行在我Air对PostgreSQL表300行:

simple_random(): 
    90.09954111799925
load_only_random():
    65.94714171699889
order_by_random():
    23.17819356000109
optimized_random():
    19.87806927999918

你可以很容易地看到,使用 func.random() 是远远快于返回的所有结果蟒蛇的 random.choice().

此外,如表格的大小的增加,性能 order_by_random() 将会显着降低,因为一个 ORDER BY 需要一个完整的表格的扫描对比 COUNToptimized_random() 可以使用一个指标。

一些SQL DBMS,即Microsoft SQL服务器,DB2, PostgreSQL 已经实施的SQL:2003年 TABLESAMPLE 条款。支持加到SQLAlchemy 1.1版.它允许返回的样本表使用不同的采样方法标准的要求 SYSTEMBERNOULLI, ,这返回所需的大致百分比表。

在SQLAlchemy FromClause.tablesample()tablesample() 是用来生产一个 TableSample 结构:

# Approx. 1%, using SYSTEM method
sample1 = mytable.tablesample(1)

# Approx. 1%, using BERNOULLI method
sample2 = mytable.tablesample(func.bernoulli(1))

有一种轻微的地方使用时映射类:该产生的 TableSample 对象必须是个别名,以便可以用来查询模型的对象:

sample = aliased(MyModel, tablesample(MyModel, 1))
res = session.query(sample).all()

由于许多答复包含性能基准,我将包括一些简单的测试这里。使用一个简单表在PostgreSQL带约一百万的行和单一整数列,选择(大约) 1%的样品:

In [24]: %%timeit
    ...: foo.select().\
    ...:     order_by(func.random()).\
    ...:     limit(select([func.round(func.count() * 0.01)]).
    ...:           select_from(foo).
    ...:           as_scalar()).\
    ...:     execute().\
    ...:     fetchall()
    ...: 
307 ms ± 5.72 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

In [25]: %timeit foo.tablesample(1).select().execute().fetchall()
6.36 ms ± 188 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

In [26]: %timeit foo.tablesample(func.bernoulli(1)).select().execute().fetchall()
19.8 ms ± 381 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

之前急于使用 SYSTEM 采样方法的一个应该知道它的样本 网页, ,而不是单个组,因此可能不适合于小表的为例。

这是解决我使用:

from random import randint

rows_query = session.query(Table)                # get all rows
if rows_query.count() > 0:                       # make sure there's at least 1 row
    rand_index = randint(0,rows_query.count()-1) # get random index to rows 
    rand_row   = rows_query.all()[rand_index]    # use random index to get random row

这是我的功能选择的随机行(s)的一个表:

from sqlalchemy.sql.expression import func

def random_find_rows(sample_num):
    if not sample_num:
        return []

    session = DBSession()
    return session.query(Table).order_by(func.random()).limit(sample_num).all()

这个解决方案将会选择一个单一的随机行

这种解决方案需要的主要关键是命名的id,它应该是如果它不是已经:

import random
max_model_id = YourModel.query.order_by(YourModel.id.desc())[0].id
random_id = random.randrange(0,max_model_id)
random_row = YourModel.query.get(random_id)
print random_row

有几种方式通过SQL,取决于其数据的基础是在使用。

(我认为SQLAlchemy可以使用所有这些反正)

mysql:

SELECT colum FROM table
ORDER BY RAND()
LIMIT 1

PostgreSQL:

SELECT column FROM table
ORDER BY RANDOM()
LIMIT 1

MSSQL:

SELECT TOP 1 column FROM table
ORDER BY NEWID()

IBM DB2:

SELECT column, RAND() as IDX
FROM table
ORDER BY IDX FETCH FIRST 1 ROWS ONLY

Oracle:

SELECT column FROM
(SELECT column FROM table
ORDER BY dbms_random.value)
WHERE rownum = 1

但是我不知道的任何标准的方式

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top