#python #join #sqlalchemy
#python #Присоединиться #sqlalchemy
Вопрос:
Я пытаюсь выполнить запрос, который работает по принципу «много-> many» между bmarks и тегами с помощью вторичной таблицы bmarks_tags. Запрос включает в себя несколько подзапросов, и мне нужно выделить столбец. Позже я хочу присоединить это к другой таблице с помощью РАЗЛИЧНЫХ идентификаторов.
Я пробовал это несколькими способами, и этот кажется наиболее близким:
tagid = alias(Tag.tid.distinct())
test = select([bmarks_tags.c.bmark_id],
from_obj=[bmarks_tags.join(DBSession.query(tagid.label('tagid'))),
bmarks_tags.c.tag_id == tagid])
return DBSession.execute(qry)
Но я получаю сообщение об ошибке:
⇝ AttributeError: '_UnaryExpression' object has no attribute 'named_with_column'
Кто-нибудь знает, как я могу выполнить объединение между bmarks_tags.tag_id и результатом Tag.tid.distinct()?
Спасибо
Схема:
# this is the secondary table that ties bmarks to tags
bmarks_tags = Table('bmark_tags', Base.metadata,
Column('bmark_id', Integer, ForeignKey('bmarks.bid'), primary_key=True),
Column('tag_id', Integer, ForeignKey('tags.tid'), primary_key=True)
)
class Tag(Base):
"""Bookmarks can have many many tags"""
__tablename__ = "tags"
tid = Column(Integer, autoincrement=True, primary_key=True)
name = Column(Unicode(255), unique=True)
Комментарии:
1. Пожалуйста, опубликуйте свою схему, чтобы мы могли ее воспроизвести.
2. Выражение SELECT выглядит довольно запутанным. У вас есть фактический SQL?
Ответ №1:
Что-то вроде этого должно сработать:
t = DBSession.query(Tag.tid.distinct().label('tid')).subquery('t')
test = select([bmarks_tags.c.bmark_id], bmarks_tags.c.tag_id == t.c.tid)
return DBSession.execute(test)
Комментарии:
1. Я думаю, это сработало бы. В итоге я просто обработал запрос совсем по-другому. Я думаю, что мне не хватало .subquery (), который помог бы мне получить что-то, что знало, что такое heck .c.tid. Псевдоним и т.д. Не позволят использовать эту ссылку. Если кто-то хочет увидеть полную рабочую реализацию / etc, вы можете проверить это здесь: goo.gl/GV9x7
2. Спасибо за это. Это был важный намек для моего решения другой проблемы, связанной с получением доступа к помеченному столбцу позже в whereclause. Решением было извлечь объект label и ссылаться на него в обоих местах, например, var_col = at.c[‘X’].label(‘var_name’) … запрос = select([at.c[‘id’], var_col], где причина=var_col != Нет)
Ответ №2:
Трудно сказать, чего вы пытаетесь достичь, но поскольку вы в любом случае используете orm (и в sa в наши дни больше нет особых причин использовать голые выборки), вам, вероятно, следует начать с установления отношения «многие ко многим»:
bmarks_tags = Table('bmark_tags', Base.metadata,
Column('bmark_id', Integer, ForeignKey('bmarks.bid'), primary_key=True),
Column('tag_id', Integer, ForeignKey('tags.tid'), primary_key=True)
)
class Tag(Base):
"""Bookmarks can have many many tags"""
__tablename__ = "tags"
tid = Column(Integer, primary_key=True)
name = Column(Unicode(255), unique=True)
class BMark(Base):
__tablename__ = 'bmarks'
bid = Column(Integer, primary_key=True)
tags = relation(Tag, secondary=bmarks_tags, backref="bmarks")
Затем получите свой запрос и переходите оттуда:
query = DBSession.query(BMark).join(BMark.tags)
Если нет, укажите нам фактический sql, который вы пытаетесь заставить sqlalchemy выдавать.