2012-05-16 3 views
2

몇 가지 알림 테이블이 있는데 모든 사용자에게 모든 알림을 표시하기 위해 모든 알림 테이블을 통합하고 싶습니다. 그러나 노조는 제대로 작동하지 않습니다.SQLAlchemy에서 여러 테이블을 통합하는 방법은 무엇입니까?

파이썬 코드

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 = 거짓) .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

2 개 이상의 쿼리로 구성된 유니온을 생성해야하며, 유니온에서 쿼리의 수는 동적입니다. sqlalchemy.sql.union() is not working. 문법은 무엇입니까? – vishal

답변

2

예상대로 쿼리가 생성되었다고 가정해도이 작업은 공용체와 함께 작동하지 않는다고 생각합니다. 세 가지 다른 객체 유형을 쿼리하고 있습니다. ORM은 데이터베이스에서 행을 다시 가져올 때 행을 올바른 클래스에 매핑하는 방법을 알지 못합니다.

세 번째 열은 세 테이블 모두에서 다른 의미를 가지고 있으므로이 경우 UNION은 의미가 없습니다.

세 가지 알림 유형이 일반적인 ORM 매핑 클래스에서 상속되지 않는 한 세 가지 쿼리를 별도로 수행해야합니다. 이 경우 SQLAlchemy는 UNION이 아닌 모든 네 가지 유형을 한꺼번에 쿼리 할 수 ​​있습니다.

+0

3 가지 별도의 쿼리를 수행 할 필요가 없습니다. 모든 알림 유형이 '알림'클래스에서 상속되기 때문에 마지막 문의 내용을 더 자세히 설명 할 수 있습니까? – BDuelz

+0

상속에 대한 SQLAlchemy의 지원을 한 번도 사용한 적이 없으며 http://docs.sqlalchemy.org/en/rel_0_7/orm/inheritance.html에서만 사용자를 가리킬 수 있습니다. 소개에서 다음 문장을 주목하십시오 : "매퍼가 상속 관계로 구성되면 SQLAlchemy는"다형성 "요소를로드 할 수 있습니다. 즉 단일 쿼리가 여러 유형의 객체를 반환 할 수 있습니다." –

+0

그레이시 아스, 한번 봐봐. – BDuelz

1

sqlalchemy를 사용하여 서로 다른 테이블을 결합하는 것은 가능합니다. 각 테이블에서 어떤 열을 가져 와서 올바르게 결합 할 수 있는지 지정해야합니다. 당신이 엔티티 AB을 말해봐,이 작업을 수행 :

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.someColumnB.someOtherColumn 동일한 유형 강제 변환 할 수없는 경우 즉, 당신의 DBMS는 수도 참조 "현실 세계"의 예를 들어 :

놀라게 라인 85, 87, 90 :

https://gerrit.wikimedia.org/r/#/c/147312/4/wikimetrics/metrics/rolling_active_editor.py 두 개의 서로 다른 테이블 unione의 하위 쿼리를 생성

d 함께. 이 하위 쿼리는 나중에 조인에 사용되며 해당 열은 보통 때와 마찬가지로 .c.column을 통해 액세스됩니다.

관련 문제