简体   繁体   中英

How to Join Query With Replaced ID From Other Table?

I have these two tables

User
| id | name  | 
| 1  | user1 |
| 2  | user2 |
| 3  | user3 |

Event
| id | name   | created_by | published_by |
| 1  | event1 |     1      |       2      |
| 2  | event2 |     2      |       2      |
| 3  | event3 |     3      |       1      |

I want to join them that when Event table is displayed, all references are replaced by actual names from User table. This how my basic join query looks like

select
  Event.id as event_id,
  Event.name as event_name,
  Event.created_by as event_created_by,
  Event.published_by as event_published_by,
  User.name as user_name
from
  Event
  left join User on created_by = User.id

which in SQLAlchemy translates to

db.session.query(Event, User).outerjoin(User, Event.created_by==User.id).all()

and produces following output

# event_id event_name event_created_by event_published_by user_name
1 1        event1     1                2                  user1
2 2        event2     2                2                  user2
3 3        event3     3                1                  user3

where in fact it should look like:

# event_id event_name event_created_by event_published_by
1 1        event1     user1            user2
2 2        event2     user2            user2
3 3        event3     user3            user1

How can I achieve that in SQLAlchemy?

Use one additional LEFT join as below-

SELECT Event.id AS event_id, 
       Event.name AS event_name, 
       Event.created_by AS event_created_by, 
       Event.published_by AS event_published_by, 
       U1.name AS event_created_by, 
       U2.name AS event_published_by
FROM Event
     LEFT JOIN User U1 ON Event.created_by = U1.id
     LEFT JOIN User U2 ON Event.published_by = U2.id;

You can do the following SQLAlchemy query to get tuples of (event, created_by_user, published_by_user) :

from sqlalchemy.orm import aliased

User1 = aliased(User)
User2 = aliased(User)

result = db.session.query(Event, User1, User2)\
    .outerjoin(User1, Event.created_by == User1.id)\
    .outerjoin(User2, Event.published_by == User2.id).all()

Which results in the following SQL:

SELECT  event.id AS event_id, 
        event.name AS event_name, 
        event.created_by AS event_created_by, 
        event.published_by AS event_published_by, 
        user_1.id AS user_1_id, 
        user_1.name AS user_1_name, 
        user_2.id AS user_2_id, 
        user_2.name AS user_2_name
FROM    event 
        LEFT OUTER JOIN user AS user_1 ON event.created_by = user_1.id 
        LEFT OUTER JOIN user AS user_2 ON event.published_by = user_2.id

And the following list of tuples:

[(<1, event1, 1, 2>, <1, user1>, <2, user2>), (<2, event2, 2, 2>, <2, user2>, <2, user2>), (<3, event3, 3, 1>, <3, user3>, <1, user1>)]

You can loop over these results getting the various values for example like this:

for event, created_by_user, published_by_user in result:
    print(event)
    print(created_by_user.name)
    print(published_by_user.name)

我认为要获得event_published_by你应该在事件和用户之间进行另一次连接,但是在user.id = event.published_by

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM