Join 无法使用SQLAlchemy上的显式联接序列(包括别名表)进行查询

Join 无法使用SQLAlchemy上的显式联接序列(包括别名表)进行查询,join,sqlalchemy,alias,explicit,Join,Sqlalchemy,Alias,Explicit,在两个表之间进行SQLAlchemy查询时遇到问题: ProcessedDataset - ID ProcDSParent - ThisDataset (foreign key to ProcessedDataset.ID) - ItsParent (foreign key to ProcessedDataset.ID) 要查找数据集的父级和子级,我需要显式 指定以下对象之间的联接顺序: ProcessedDataset ProcessedDataset 在为他们

在两个表之间进行SQLAlchemy查询时遇到问题:

ProcessedDataset
    - ID 
ProcDSParent
    - ThisDataset (foreign key to ProcessedDataset.ID)
    - ItsParent   (foreign key to ProcessedDataset.ID)
要查找数据集的父级和子级,我需要显式 指定以下对象之间的联接顺序: ProcessedDataset ProcessedDataset

在为他们制作了不同的别名之后,我尝试了不同的连接方法, 但仍然无法得到它

使用“查找数据集的父项”演示:

方法: FromClause.join+expression.select 方法: orm.join+expression.select 如您所见,它们都不是数据集的父级,数据集应为:

SELECT `ProcessedDataset_ItsParent`.`Name`
FROM `ProcessedDataset` 
   INNER JOIN `ProcDSParent` AS `ThisDataset_ItsParent` ON  
          `ProcessedDataset`.`ID` = `ThisDataset_ItsParent`.`ThisDataset`
   INNER JOIN `ProcessedDataset` AS `ProcessedDataset_ItsParent` ON
          `ThisDataset_ItsParent`.'ItsParent` = `ProcessedDataset_ItsParent`.`ID`
WHERE `ProcessedDataset`.`Name` = %s
感谢您的帮助,已经在这里呆了几天了

侗族

附加最小DDL和python代码 ds0,ds2->ds1->ds3->ds4

ds5、ds7->ds6

from sqlalchemy import Table, create_engine, MetaData
from sqlalchemy import and_
from sqlalchemy.sql import select
from sqlalchemy.orm import join


url = 'mysql://cms:passcms@localhost:3306/testbed'
engine = create_engine(url, strategy = 'threadlocal')
kwargs = {'autoload':True}
db_meta = MetaData()
db_meta.bind = engine

dataset = Table('ProcessedDataset', db_meta, **kwargs)
dsparent = Table('ProcDSParent', db_meta, **kwargs)

parent = dataset.alias('ProcessedDataset_ItsParent')
child_parent = dsparent.alias('ThisDataset_ItsParent')

keylist = [parent.c.Name]
whereclause = dataset.c.Name.op('=')('ds0')

r_join = dataset
r_join.join(child_parent, dataset.c.ID == child_parent.c.ThisDataset)
r_join.join(parent, child_parent.c.ItsParent == parent.c.ID)

query = select(keylist, whereclause)
print query
print engine.execute(query).fetchall()

query.append_from(r_join)
print query
print engine.execute(query).fetchall()

query = select(keylist, from_obj=r_join, whereclause=whereclause)
print query
print engine.execute(query).fetchall()

join2 = join(dataset, child_parent, dataset.c.ID == child_parent.c.ThisDataset)
join2.join(dsparent, child_parent.c.ItsParent == parent.c.ID)


query.append_from(join2)
print query
print engine.execute(query).fetchall()

query = select(keylist, from_obj=join2, whereclause=whereclause)
print query
print engine.execute(query).fetchall()

迈克尔·拜耳通过邮件回复了我的问题

join方法返回一个新的join对象,即表示连接的对象。原始对象不变:

r_join = dataset
r_join = r_join.join(child_parent, ...)
r_join = r_join.join(parent, ...)
我还试用了orm.join:


你能创建一个独立的测试用例吗?@plaes附带了最小的DDL和Python代码,你能帮我吗?
SELECT `ProcessedDataset_ItsParent`.`Name`
FROM `ProcessedDataset` 
   INNER JOIN `ProcDSParent` AS `ThisDataset_ItsParent` ON  
          `ProcessedDataset`.`ID` = `ThisDataset_ItsParent`.`ThisDataset`
   INNER JOIN `ProcessedDataset` AS `ProcessedDataset_ItsParent` ON
          `ThisDataset_ItsParent`.'ItsParent` = `ProcessedDataset_ItsParent`.`ID`
WHERE `ProcessedDataset`.`Name` = %s
CREATE TABLE ProcessedDataset
  (
    ID                    BIGINT UNSIGNED not null auto_increment,
    Name                  varchar(500)      not null,

    primary key(ID)
  ) ;


CREATE TABLE ProcDSParent
  (
    ID                    BIGINT UNSIGNED not null auto_increment,
    ThisDataset           BIGINT UNSIGNED   not null,
    ItsParent             BIGINT UNSIGNED   not null,

    primary key(ID),
    unique(ThisDataset,ItsParent)
  ) ;

ALTER TABLE ProcDSParent ADD CONSTRAINT 
    ProcDSParent_ThisDataset_FK foreign key(ThisDataset) references ProcessedDataset(ID) on delete CASCADE
;
ALTER TABLE ProcDSParent ADD CONSTRAINT 
    ProcDSParent_ItsParent_FK foreign key(ItsParent) references ProcessedDataset(ID) on delete CASCADE
;

INSERT INTO ProcessedDataset VALUES (0, "ds0");
INSERT INTO ProcessedDataset VALUES (1, "ds1");
INSERT INTO ProcessedDataset VALUES (2, "ds2");
INSERT INTO ProcessedDataset VALUES (3, "ds3");
INSERT INTO ProcessedDataset VALUES (4, "ds4");
INSERT INTO ProcessedDataset VALUES (5, "ds5");
INSERT INTO ProcessedDataset VALUES (6, "ds6");
INSERT INTO ProcessedDataset VALUES (7, "ds7");

INSERT INTO ProcDSParent VALUES (0, 0, 1);
INSERT INTO ProcDSParent VALUES (1, 2, 1);
INSERT INTO ProcDSParent VALUES (2, 1, 3);
INSERT INTO ProcDSParent VALUES (3, 3, 4);
INSERT INTO ProcDSParent VALUES (4, 5, 6);
INSERT INTO ProcDSParent VALUES (5, 7, 6);
from sqlalchemy import Table, create_engine, MetaData
from sqlalchemy import and_
from sqlalchemy.sql import select
from sqlalchemy.orm import join


url = 'mysql://cms:passcms@localhost:3306/testbed'
engine = create_engine(url, strategy = 'threadlocal')
kwargs = {'autoload':True}
db_meta = MetaData()
db_meta.bind = engine

dataset = Table('ProcessedDataset', db_meta, **kwargs)
dsparent = Table('ProcDSParent', db_meta, **kwargs)

parent = dataset.alias('ProcessedDataset_ItsParent')
child_parent = dsparent.alias('ThisDataset_ItsParent')

keylist = [parent.c.Name]
whereclause = dataset.c.Name.op('=')('ds0')

r_join = dataset
r_join.join(child_parent, dataset.c.ID == child_parent.c.ThisDataset)
r_join.join(parent, child_parent.c.ItsParent == parent.c.ID)

query = select(keylist, whereclause)
print query
print engine.execute(query).fetchall()

query.append_from(r_join)
print query
print engine.execute(query).fetchall()

query = select(keylist, from_obj=r_join, whereclause=whereclause)
print query
print engine.execute(query).fetchall()

join2 = join(dataset, child_parent, dataset.c.ID == child_parent.c.ThisDataset)
join2.join(dsparent, child_parent.c.ItsParent == parent.c.ID)


query.append_from(join2)
print query
print engine.execute(query).fetchall()

query = select(keylist, from_obj=join2, whereclause=whereclause)
print query
print engine.execute(query).fetchall()
r_join = dataset
r_join = r_join.join(child_parent, ...)
r_join = r_join.join(parent, ...)
join1 = join(child_parent, dataset, child_parent.c.ThisDataset == dataset.c.ID)
join2 = parent.join(join1, parent.c.ID == child_parent.c.ItsParent)