2014-07-02 31 views
6

SQLAlchemy içindeki iç kümeler için (bkz. here) aşağıdaki sorguyu uygulamaya çalışıyorum. Ne ile uğraştığım, SELECT sorgusundaki depth sorgusundaki (SELECT sorgusuna bağlı olarak) etiketli depth hesaplamanın, sondaki HAVING maddesinde nasıl kullanılacağıdır.SQLAlchemy içindeki Etiketleri Kullanma() SQLAlchemy İçerisindeki Madde Kullanımı

node = aliased(Category)                    
parent = aliased(Category)                   
sub_parent = aliased(Category) 

sub_tree = DBSession.query(node.name,                 
    (func.count(parent.name) - 1).label('depth')).\             
    filter(node.lft.between(parent.lft, parent.rgt)).\            
    filter(node.name == category_name).\                
    group_by(node.name).\                    
    order_by(node.lft).subquery()                  

children = DBSession.query(node.name,                 
    (func.count(parent.name) - (sub_tree.c.depth + 1)).label('depth')).\        
    filter(node.lft.between(parent.lft, parent.rgt)).\ 
    filter(node.lft.between(sub_parent.lft, sub_parent.rgt)).\          
    filter(sub_parent.name == sub_tree.c.name).\              
    group_by(node.name).having(depth <= 1).\              
    order_by(node.lft).all() 

Ama hatayı alıyorum sonunda:

SELECT node.name, (COUNT(parent.name) - (sub_tree.depth + 1)) AS depth 
FROM nested_category AS node, 
    nested_category AS parent, 
    nested_category AS sub_parent, 
    (
      SELECT node.name, (COUNT(parent.name) - 1) AS depth 
      FROM nested_category AS node, 
        nested_category AS parent 
      WHERE node.lft BETWEEN parent.lft AND parent.rgt 
        AND node.name = 'PORTABLE ELECTRONICS' 
      GROUP BY node.name 
      ORDER BY node.lft 
    )AS sub_tree 
WHERE node.lft BETWEEN parent.lft AND parent.rgt 
    AND node.lft BETWEEN sub_parent.lft AND sub_parent.rgt 
    AND sub_parent.name = sub_tree.name 
GROUP BY node.name 
HAVING depth <= 1 
ORDER BY node.lft; 

ı kullanırken ben çok yakın olduğum gibi hissediyorum

NameError: global name 'depth' is not defined 

çeşit mantıklı hangisi.

HAVING count(%s) <= %s 

Gerçekten tam olarak okumak için gerekenler: Ben having(func.count('depth') <= 1 ile having(depth <= 1) yerine, ben (% s tutucuları ('derinliği', nerede 1)) sonuç verir oluşturulan aşağıdaki HAVING fıkra ile bitirmek şunun gibidir:

Herhangi bir fikri olan var mı?

Benim son çare aslında yerine ORM tabakasının geçiyor ham Sorgunun uygulanacağı, ama önceden çok daha iyi olur Gelmek üzereyim çünkü ...

Teşekkür ederim.

Düzenleme:

Ben de aşağıdaki kodu denedim ama ('derinlik' etiketi daima 0 olması gibi) doğru sonuç vermez:

node = aliased(Category)                    
parent = aliased(Category)                   
sub_parent = aliased(Category) 

sub_tree_depth = (func.count(parent.name) - 1).label('depth') 
depth = (func.count(parent.name) - (sub_tree_depth + 1)).label('depth') 

sub_tree = DBSession.query(node.name, 
    sub_tree_depth).\ 
    filter(node.lft.between(parent.lft, parent.rgt)).\ 
    filter(node.name == category_name).\ 
    group_by(node.name).\ 
    order_by(node.lft).subquery() 

children = DBSession.query(node.name, 
    depth).\ 
    filter(node.lft.between(parent.lft, parent.rgt)).\ 
    filter(node.lft.between(sub_parent.lft, sub_parent.rgt)).\ 
    filter(sub_parent.name == sub_tree.c.name).\ 
    group_by(node.name).having(depth <= 1).\ 
    order_by(node.lft).all() 

Bu şekilde oluşturulan HAVING tümceciğine benziyor (categories_2 == orijinal sorguda parent):

Düzenleme: Ben oluşturulan SQL eklemek faydalı olacağını düşündüm

.

Kişisel SQL sorgusu örtülü sqlalchemy içinde bunları açıkça tanımlamak gerekir katılır kullanır SQL

'SELECT categories_1.name AS categories_1_name, count(categories_2.name) - (anon_1.depth + %s) AS depth 
FROM categories AS categories_1, categories AS categories_2, (SELECT categories_1.name AS name, count(categories_2.name) - %s AS depth 
FROM categories AS categories_1, categories AS categories_2 
WHERE categories_1.lft BETWEEN categories_2.lft AND categories_2.rgt AND categories_1.name = %s GROUP BY categories_1.name ORDER BY categories_1.lft) AS anon_1, categories AS categories_3 
WHERE categories_1.lft BETWEEN categories_2.lft AND categories_2.rgt AND categories_1.lft BETWEEN categories_3.lft AND categories_3.rgt AND categories_3.name = anon_1.name GROUP BY categories_1.name 
HAVING count(categories_2.name) - (anon_1.depth + %s) <= %s ORDER BY categories_1.lft' (1, 1, u'Institutional', 1, 1) 
+0

"HAVING" deyiminde "HAVING (COUNT (parent.name) - 1) = 1 ' – Charlesliam

+0

gibi tüm derinliği filtre olarak kullanmayı denediniz. Yanıt için teşekkürler. Doğru sonuçları vermeyen HAVING (COUNT (parent.name) - 1) = 1 'kullanmayı denedim. Daha sonra HAVING (COUNT (parent.name) - (sub_tree.depth + 1)) <= 1 'den denedim, bu da 'Bilinmeyen sütun' sub_tree.depth 'SQL hatasıyla sonuçlandı.'… – dhildreth

cevap

5

Oluşturulan

node = aliased(Category) 
parent = aliased(Category) 
sub_parent = aliased(Category) 

sub_tree = DBSession.query(node.name, 
    (func.count(parent.name) - 1).label('depth')).\ 
    filter(node.lft.between(parent.lft, parent.rgt)).\ 
    filter(node.name == category_name).\ 
    group_by(node.name).\ 
    order_by(node.lft).subquery() 

depth = (func.count(parent.name) - (sub_tree.c.depth + 1)).label('depth') 
children = DBSession.query(node.name, depth).\ 
    filter(node.lft.between(parent.lft, parent.rgt)).\ 
    filter(node.lft.between(sub_parent.lft, sub_parent.rgt)).\ 
    filter(sub_parent.name == sub_tree.c.name).\ 
    group_by(node.name).having(depth <= 1).\ 
    order_by(node.lft) 

SQLAlchemy.Diğer ikinci deneyin neredeyse doğru olduğunu daha: Oluşturulan SQL HAVING fıkra yerine onun takma tekrarlanan tam ifadeye sahip olacak eğer

node = aliased(Category) parent = aliased(Category) sub_parent = aliased(Category) sub_tree = DBSession.query(node.name, (func.count(parent.name) - 1).label('depth')).\ join(parent, node.lft.between(parent.lft, parent.rgt)).\ filter(node.name == category_name).\ group_by(node.name).\ order_by(node.lft).subquery() depth = (func.count(parent.name) - (sub_tree.c.depth + 1)).label('depth') children = DBSession.query(node.name, depth).\ join(parent, node.lft.between(parent.lft, parent.rgt)).\ join(sub_parent, node.lft.between(sub_parent.lft, sub_parent.rgt)).\ join(sub_tree, sub_parent.name == sub_tree.c.name).\ group_by(node.name, sub_tree.c.depth).\ having(depth <= 1).\ order_by(node.lft).all() 

şaşırmayın. SQLAlchemy çoğu durumda çalışan SQL üretmek için çabalarken, takma adlar burada izin verilmez, sadece MySQL uzantısı.

+0

Bunu gerçekten takdir ediyorum . Ancak, '' clause '' içinde 'Bilinmeyen sütun' anon_1.depth 'hata mesajı alıyorum. Oluşturulan SQL'in tamamını yayınlayamıyorum, ancak önemli olanın şu olduğunu düşünüyorum: 'HAVING sayım (category_2.name) - (anon_1.depth + 1) <= 1' – dhildreth

+0

Görünmüyorsa, SQLAlchemy, "sub_tree" yi "anon_1" ve "category_2" öğelerine "parent" olarak atar. – dhildreth

+0

Cevabımı güncelledim, başta eksik olanları fark etmedim ... Umarım şimdi işe yarayacaktır. –