2014-07-23 7 views
8

मुझे अपने स्क्लेक्लेमी प्रश्नों को अनुकूलित करने में कठिनाई हो रही है। मेरा एसक्यूएल ज्ञान बहुत बुनियादी है, और मुझे बस एसक्यूएलकेमी डॉक्स से सामान की आवश्यकता नहीं मिल सकती है।SQLAlchemy: एक प्रश्न में कई मायने रखता है

class Parent(Base): 
    __tablename__ = "parents" 
    id = Column(Integer, primary_key = True) 
    children = relationship("Child", backref = "parent") 

class Child(Base): 
    __tablename__ = "children" 
    id = Column(Integer, primary_key = True) 
    parent_id = Column(Integer, ForeignKey("parents.id")) 
    naughty = Column(Boolean) 

मैं कैसे कर सकता है:

निम्नलिखित बहुत ही बुनियादी एक-से-अनेक संबंध मान लीजिए

  • हर माता-पिता के लिए (Parent, count_of_naughty_children, count_of_all_children) की क्वेरी tuples?

सभ्य समय के बाद googling खर्च, मैंने पाया अलग से उन मूल्यों को क्वेरी करने के लिए कैसे:

# The following returns tuples of (Parent, count_of_all_children): 
session.query(Parent, func.count(Child.id)).outerjoin(Child, Parent.children).\ 
    group_by(Parent.id) 
# The following returns tuples of (Parent, count_of_naughty_children): 
al = aliased(Children, session.query(Children).filter_by(naughty = True).\ 
    subquery()) 
session.query(Parent, func.count(al.id)).outerjoin(al, Parent.children).\ 
    group_by(Parent.id) 

मैं उन्हें अलग अलग तरीकों से गठबंधन करने की कोशिश की, लेकिन मैं क्या चाहते हैं पाने के लिए प्रबंधन नहीं किया।

  • सभी माता-पिता से पूछें जिनमें 80% से अधिक शरारती बच्चे हैं? संपादित करें: शरारती पूर्ण हो सकता है।

मुझे लगता है कि यह क्वेरी पिछले एक पर आधारित होगी, शरारती/सभी अनुपात द्वारा फ़िल्टरिंग।

किसी भी मदद की सराहना की जाती है।

संपादित करें: अंटी Haapala की मदद के लिए धन्यवाद, मैंने पाया दूसरा सवाल का हल:

avg = func.avg(func.coalesce(Child.naughty, 0)) # coalesce() treats NULLs as 0 
# avg = func.avg(Child.naughty) - if you want to ignore NULLs 
session.query(Parent).join(Child, Parent.children).group_by(Parent).\ 
    having(avg > 0.8) 

यह औसत पाता है बच्चों के naughty चर, झूठी इलाज और 0 के रूप में NULLs, और यह सच है के रूप में 1. परीक्षण किया MySQL बैकएंड के साथ, लेकिन दूसरों पर भी काम करना चाहिए।

उत्तर

7

count() एसक्यूएल aggretate समारोह की तरह कुछ बहुत सरल है मिलता है, यह आपको प्रत्येक समूह में गैर-शून्य मानों की कुल संख्या देता है। इसे ध्यान में रखते हुए, हम आपको उचित परिणाम देने के लिए अपनी क्वेरी समायोजित कर सकते हैं।

print (Query([ 
    Parent, 
    func.count(Child.id), 
    func.count(case(
     [((Child.naughty == True), Child.id)], else_=literal_column("NULL"))).label("naughty")]) 

    .join(Parent.children).group_by(Parent) 
    ) 

निम्नलिखित में से कौन एसक्यूएल का उत्पादन:

SELECT 
parents.id AS parents_id, 
count(children.id) AS count_1, 
count(CASE WHEN (children.naughty = 1) 
     THEN children.id 
     ELSE NULL END) AS naughty 
FROM parents 
JOIN children ON parents.id = children.parent_id 
GROUP BY parents.id 
+0

को ठीक करने में मदद की, धन्यवाद, यह पूरी तरह से काम करता है! – meandrobo

4

यदि आपकी क्वेरी केवल उन माता-पिता को प्राप्त करने के लिए है जिनके पास 80% बच्चे शरारती हैं, तो आप अधिकतर डेटाबेस पर naughty को पूर्णांक में डाल सकते हैं, फिर इसका औसत लें; तो having यह औसत 0.8 से अधिक है।

इस प्रकार आप

from sqlalchemy.sql.expression import cast 

naughtyp = func.avg(cast(Child.naughty, Integer)) 
session.query(Parent, func.count(Child.id), naughtyp).join(Child)\ 
    .group_by(Parent.id).having(naughtyp > 0.8).all() 
+0

धन्यवाद एक बहुत, कि चाल किया था। लेकिन मैंने उल्लेख नहीं किया कि मेरे असली मॉडल "शरारती" में शून्य हो सकता है - क्षमा करें, मेरी गलती। औसत मूल्यों को औसत से अनदेखा किया जा रहा है, इसलिए यह समाधान बिल्कुल वही नहीं है जो मैं चाहता हूं। – meandrobo

+2

func.coalesce() ने मुझे यह ^^ – meandrobo

संबंधित मुद्दे