我有几个不同的通知表,我想在所有这些通知表中执行联合,以向用户显示所有通知。但是,工会没有按预期工作。
Python代码
def _get_notifications_query(self, unconfirmed_only=True):
'''
Return base query to return this users notifications.
@param unconfirmed_only
@return Query object
'''
requests = (
DBSession.query(FriendshipRequestNotification)
.outerjoin(UserFriendshipRequestNotification,
UserFriendshipRequestNotification.notification_id==FriendshipRequestNotification.id)
.filter(UserFriendshipRequestNotification.user_id==self.id))
confirmations = (
DBSession.query(FriendshipConfirmationNotification)
.outerjoin(UserFriendshipConfirmationNotification,
UserFriendshipConfirmationNotification.notification_id==FriendshipConfirmationNotification.id)
.filter(UserFriendshipConfirmationNotification.user_id==self.id))
comments = (
DBSession.query(CommentNotification)
.outerjoin(UserCommentNotification,
UserCommentNotification.notification_id==CommentNotification.id)
.filter(UserCommentNotification.user_id==self.id))
if unconfirmed_only:
requests.filter(UserFriendshipRequestNotification.is_confirmed==False)
confirmations.filter(UserFriendshipConfirmationNotification.is_confirmed==False)
comments.filter(UserCommentNotification.is_confirmed==False)
return requests.union(confirmations, comments)
使用:user._get_notifications_query(unconfirmed_only = False).all()
SQL生成
SELECT anon_1.friendship_request_notifications_id AS anon_1_friendship_request_notifications_id, anon_1.friendship_request_notifications_created_at AS anon_1_friendship_request_notifications_created_at, anon_1.friendship_request_notifications_requester_id AS anon_1_friendship_request_notifications_requester_id
FROM (SELECT friendship_request_notifications.id AS friendship_request_notifications_id, friendship_request_notifications.created_at AS friendship_request_notifications_created_at, friendship_request_notifications.requester_id AS friendship_request_notifications_requester_id
FROM friendship_request_notifications LEFT OUTER JOIN users_friendship_request_notifications ON users_friendship_request_notifications.notification_id = friendship_request_notifications.id
WHERE users_friendship_request_notifications.user_id = ? UNION SELECT friendship_confirmation_notifications.id AS friendship_confirmation_notifications_id, friendship_confirmation_notifications.created_at AS friendship_confirmation_notifications_created_at, friendship_confirmation_notifications.accepter_id AS friendship_confirmation_notifications_accepter_id
FROM friendship_confirmation_notifications LEFT OUTER JOIN users_friendship_confirmation_notifications ON users_friendship_confirmation_notifications.notification_id = friendship_confirmation_notifications.id
WHERE users_friendship_confirmation_notifications.user_id = ? UNION SELECT comment_notifications.id AS comment_notifications_id, comment_notifications.created_at AS comment_notifications_created_at, comment_notifications.comment_id AS comment_notifications_comment_id
FROM comment_notifications LEFT OUTER JOIN users_comment_notifications ON users_comment_notifications.notification_id = comment_notifications.id
WHERE users_comment_notifications.user_id = ?) AS anon_1
我希望这些内容符合
SELECT * FROM friendship_request_notifications
UNION
SELECT * FROM friendship_confirmation_notifications
UNION
SELECT * FROM comment_notifications
另外,有没有办法从SQLAlchemy中对聚合的联合结果进行排序?
修改
我应该提到sqlalchemy.sql.union()
产生正确的SQL,但我不知道如何利用ORM中的那些(返回/计算记录)。
答案 0 :(得分:3)
使用sqlalchemy将不同的表联合起来当然是可能的,您只需指定从每个表中获取的列,以便它们可以正确组合。假设您有实体A
和B
,请执行以下操作:
from sqlalchemy.sql.expression import label
...
a = session.query(label('col1', A.someColumn))
b = session.query(label('col1', B.someOtherColumn))
both = a.union_all(b)
在这种情况下,您必须要注意的是,如果A.someColumn
和B.someOtherColumn
无法强制转换为相同的类型,那么您的dbms可能会吓坏:)
有关“真实世界”中的示例,请参阅第85,87和90行:
https://gerrit.wikimedia.org/r/#/c/147312/4/wikimetrics/metrics/rolling_active_editor.py
这会创建两个联合在一起的不同表的子查询。然后,该子查询将在稍后的连接中使用,其列将照常通过.c.column
访问。
答案 1 :(得分:2)
我认为这不能用于联合,即使假设查询是按照您的预期生成的。您正在查询三种不同的对象类型。当ORM从数据库中获取行时,我没有办法将行映射到正确的类。
在这种情况下,UNION没有多大意义,因为第三列在所有三个表中具有不同的含义。
除非您的三种通知类型继承自公共ORM映射类,否则应分别执行三个查询。在这种情况下,SQLAlchemy支持同时查询所有四种类型,但不支持使用UNION。