SQLAlchemy का उपयोग करके मैं किसी तालिका से एक या अधिक यादृच्छिक पंक्तियों का चयन कैसे करूं?
जवाबों:
यह एक डेटाबेस-विशिष्ट समस्या है।
मुझे पता है कि PostgreSQL, SQLite, 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 में, यादृच्छिक रिकॉर्ड का चयन करने से गंभीर पूर्णता संबंधी समस्याएं होती हैं; यहाँ इसके बारे में अच्छा लेख है।
session.query(MyModel).order_by(func.rand()).first
session.query(MyModel).order_by(func.rand()).first()
func.random()
एक सामान्य कार्य है जो डेटाबेस के यादृच्छिक कार्यान्वयन के लिए संकलित है।
यदि आप orm का उपयोग कर रहे हैं और तालिका बड़ी नहीं है (या आपके पास इसकी पंक्तियाँ कैश की गई हैं) और आप चाहते हैं कि यह डेटाबेस से स्वतंत्र हो जो वास्तव में सरल दृष्टिकोण है।
import random
rand = random.randrange(0, session.query(Table).count())
row = session.query(Table)[rand]
यह थोड़ा धोखा दे रहा है लेकिन यही कारण है कि आप एक orm का उपयोग करते हैं।
random.choice(session.query(Table))
?
एक यादृच्छिक पंक्ति खींचने का एक सरल तरीका है जो आईएस डेटाबेस स्वतंत्र है। बस .offset () का उपयोग करें। सभी पंक्तियों को खींचने की आवश्यकता नहीं है:
import random
query = DBSession.query(Table)
rowCount = int(query.count())
randomRow = query.offset(int(rowCount*random.random())).first()
जहां टेबल आपकी टेबल है (या आप वहां कोई प्रश्न रख सकते हैं)। यदि आप कुछ पंक्तियाँ चाहते हैं, तो आप बस इसे कई बार चला सकते हैं, और यह सुनिश्चित कर सकते हैं कि प्रत्येक पंक्ति पहले की तरह नहीं है।
query.offset(random.randrange(rowCount)).limit(1).first()
।
.limit(1)
पहले इस्तेमाल करने का कोई कारण है .first()
? यह बेमानी लगता है। शायद, query.offset(random.randrange(row_count)).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
300 पंक्तियों के साथ एक पोस्टग्रेक्यूएल टेबल के खिलाफ मेरी मैकबुक पर 10,000 रन के लिए परिणाम:
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
एक पूर्ण तालिका स्कैन बनाम की आवश्यकता है COUNT
में optimized_random()
एक सूचकांक का उपयोग कर सकते हैं।
random.sample()
करें? यहाँ अनुकूलित तरीका क्या है?
flask-sqlalchemy
?
कुछ SQL DBMS, अर्थात् Microsoft SQL सर्वर, DB2 और PostgreSQL ने SQL: 2003 TABLESAMPLE
क्लॉज लागू किया है । 1.1 संस्करण में SQLAlchemy में समर्थन जोड़ा गया था । यह विभिन्न नमूने विधियों का उपयोग करके तालिका का एक नमूना वापस करने की अनुमति देता है - मानक की आवश्यकता होती है SYSTEM
और BERNOULLI
, जो तालिका के वांछित अनुमानित प्रतिशत को वापस करते हैं।
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
यह एक तालिका की यादृच्छिक पंक्ति (ओं) का चयन करने के लिए मेरा कार्य है:
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()
डेटाबेस से एक यादृच्छिक सवाल चुनने पर इस उदाहरण का सबसे सरल विधि का उपयोग करें: -
#first import the random module
import random
#then choose what ever Model you want inside random.choise() method
get_questions = random.choice(Question.query.all())
इस समाधान के लिए आवश्यक है कि प्राथमिक कुंजी को नाम दिया गया है, यह होना चाहिए यदि इसकी पहले से ही नहीं:
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
एसक्यूएल के माध्यम से कुछ तरीके हैं, जिसके आधार पर डेटा बेस का उपयोग किया जा रहा है।
(मुझे लगता है कि SQLAlchemy इन सभी का उपयोग कर सकता है)
माई एसक्यूएल:
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()
आईबीएम DB2:
SELECT column, RAND() as IDX
FROM table
ORDER BY IDX FETCH FIRST 1 ROWS ONLY
आकाशवाणी:
SELECT column FROM
(SELECT column FROM table
ORDER BY dbms_random.value)
WHERE rownum = 1
हालाँकि मुझे किसी मानक तरीके की जानकारी नहीं है
select.order_by(func.random()).limit(n)