2016-01-31 2 views
2

Изначально я пытался сделать «Прямое внешнее соединение», но как только я узнал, что это не поддерживается, я начал работать с приходом слева. Тем не менее, мне трудно понять, как писать то, что мне нужно. По существу у меня есть две таблицы: Table_1 и Table_2, и мне нужны все строки от Table_1, где column_c равно 1. Кроме того, мне нужны все строки от Table_2, где column_b еще не в Table 1. Визуально это выглядит примерно так:Flask-SQLAlchemy Left Outer Присоединиться к фильтруемому запросу

**Table_1** 
column_a (a and b are the 
column_b (primary key. 
column_c 

**Table_2** 
column_b 

Это как бы я писать в SQL:

SELECT * 
FROM (SELECT * FROM Table_1 WHERE column_a = 123) t1 
RIGHT OUTER JOIN Table_2 t2 ON t1.column_b = t2.column_b 
WHERE t1.column_c = 1 or t1.column_c is NULL; 

SELECT * 
FROM Table_2 t2 
LEFT OUTER JOIN (SELECT * FROM Table_1 WHERE column_a = 123) t1 
ON Table_2 t2 ON t1.column_b = t2.column_b 
WHERE t1.column_c = 1 or t1.column_c is NULL; 

Это то, что я имею в Колба-SQLAlchemy форме, важно отметить, что это метод в классе db.Model Table_2.

def all_exclude(self, column_a): 
    return self.query.outerjoin(
     Table_1, 
     Table_1.column_b==Table_2.column_b).filter(or_(
      Table_1.column_c==None, 
      and_(Table_1.column_c==1, 
       Table_1.column_a==column_a))).all() 

К сожалению, я не думал об этом, когда я писал это, и это не будет действительно работать таким образом, так как я не могу вызвать метод из формы класса. Я должен был бы сделать это после инициализации запроса, который будет только из одной строки, а это не то, что мне нужно. Я понимаю, что я мог бы запустить его в качестве запроса, как так:

Business.query.outerjoin(
    Table_1, 
    Table_1.column_b==Table_2.column_b).filter(or_(
     Table_1.column_c==None, 
     and_(Table_1.column_c==1, 
      Table_1.column_a==column_a))).all() 

Но я стараюсь, чтобы мои классы отдельно для целей ООП, но даже тогда я не думаю, что будет работать, так как технически фильтр ISN» t до объединения. Может быть, решение проще, чем я думаю, но я не могу полностью обвести вокруг себя. Заранее спасибо!

+0

Over-усложнению это слово нуждается здесь! Прежде всего, почему вы пишете свою «ПРАВУЮ ВНУТРЕННУЮ РАБОТУ» так, как вы это делаете? Вам также нужно выбрать только те строки из 'Table_1', чей' column_a = 123'? И почему вы используете 'или t1.column_c IS NULL', вам не нужны только строки из' Table_1', которые имеют 'column_c = 1'? –

+0

@SameerMirji Ну мне нужны все строки из 'Table_1', где' column_a = 123' и 'column_c = 1'. Кроме того, мне нужны все строки из «Table_2», у которых нет «column_b», который является частью первичного ключа в таблице «Таблица_1», до 123. Это отношение «многие ко многим», где «Таблица_1» - это таблица ассоциаций для ' Таблица_2' и другая таблица. Первичный ключ представляет собой комбинацию «Таблица_2» ('column_b') и другая таблица (' column_a'). По сути, я пытаюсь избежать представления строки, которая могла бы привести к дублированию записи, если она была выбрана. – ThatTechGuy

ответ

3

Основываясь на ваш комментарий, это должно ответить на ваш вопрос:

SELECT Table_1.column_a, Table_1.column_b 
    FROM Table_1 
WHERE Table_1.column_a = 123 
    AND Table_1.column_c = 1 
UNION 
SELECT Table_2.column_a, Table_2.column_b /* I'm assuming these columns exist in Table_2. Make sure these columns are same as selected columns from Table_1 */ 
    FROM Table_2 
WHERE NOT EXISTS (SELECT 1 FROM Table_1 
        WHERE Table_1.column_b = Table_2.column_b 
         AND Table_1.column_a = 123); 

Это переводит в Python SQLAlchemy для:

from sqlalchemy import exists 

query_1 = (db.session.query(Table_1) 
      .with_entities(Table_1.column_a, Table_1.column_b) 
      .filter(Table_1.column_a == 123) 
      .filter(Table_1.column_c == 1) 

query_2 = (db.session.query(Table_2) 
      .with_entities(Table_2.column_a, Table_2.column_b) 
      .filter(
       ~exists().where(Table_1.column_b == Table_2.column_b) 
      ) 
      ) 
query = query_1.union(query_2).all() 
+0

'column_a' не включен в' Table_2', а 'column_b'. Тем не менее, я думаю, что он должен по большей части работать. Я немного поиграю с ним и сделаю это. Тем не менее, я бы предпочел, чтобы мы могли сделать это с помощью соединения, как показано в стандартном SQL. – ThatTechGuy

+0

По какой причине вам нужен запрос с соединением? Поскольку вам нужны эксклюзивные строки из каждой из таблиц (w.r.t. column_b), это не очень хороший способ добиться этого при соединении. Вышеупомянутый запрос объединения имеет минимальную стоимость ЦП и количество запросов, выполненных для этого, всего 1. –

+0

Действительно? Ну, тогда это на самом деле лучше. По какой-то причине я думал, что соединение с встроенным представлением будет иметь лучшую производительность. Но я возьму ваше слово в союзе и сделаю это. Благодаря! – ThatTechGuy

Смежные вопросы