Ich habe die folgenden zwei Tabellen:

Nutzer

userid | email | phone  
1 | some@email.com | 555-555-5555  
2 | some@otheremail.com | 555-444-3333  
3 | one@moreemail.com | 333-444-1111
4 | last@one.com | 123-333-2123

UserTag

id | user_id | tag  
1 | 1 | tag1  
2 | 1 | tag2  
3 | 1 | cool_tag  
4 | 1 | some_tag  
5 | 2 | new_tag  
6 | 2 | foo  
6 | 4 | tag1

Ich möchte eine Abfrage in SQLAlchemy ausführen, um diese beiden Tabellen zu verbinden und alle Benutzer zurückzugeben, die NICHT die Tags "tag1" oder "tag2" haben. In diesem Fall sollte die Abfrage Benutzer mit Benutzer-ID 2 und 3 zurückgeben. Jede Hilfe wäre sehr dankbar.

Ich brauche das Gegenteil dieser Abfrage:

users.join(UserTag, User.userid == UserTag.user_id)
    .filter(
        or_(
            UserTag.tag.like('tag1'),
            UserTag.tag.like('tag2')
        ))
    )

Ich habe stundenlang daran gearbeitet, aber am Ende immer die falschen Benutzer oder manchmal alle. Eine SQL-Abfrage, die dies erreicht, wäre ebenfalls hilfreich. Ich werde versuchen, das in SQLAlchemy umzuwandeln.

0
Kentor 26 Nov. 2013 im 12:20

3 Antworten

Beste Antwort

Ich bin mir nicht sicher, wie dies in SQLAlchemy aussehen würde, aber hoffentlich hilft Ihnen eine Erklärung, warum die Abfrage so ist, wie sie ist, dorthin zu gelangen.

Dies ist eine äußere Verknüpfung. Sie möchten alle Datensätze aus einer Tabelle (Benutzer), auch wenn die andere Tabelle keine Datensätze enthält (UserTag). Wenn wir Benutzer an die erste Stelle setzen, handelt es sich um eine linke Verknüpfung. Darüber hinaus möchten Sie alle Datensätze, die im UserTag nicht mit einem bestimmten Filter übereinstimmen.

SELECT user.user_id, email, phone
  FROM user LEFT JOIN usertag
  ON usertag.user_id = user.user_id
    AND usertag.tag IN ('tag1', 'tag2')
  WHERE usertag.user_id IS NULL;
1
Bell 26 Nov. 2013 im 20:16

Angenommen, Ihr Modell definiert eine Beziehung wie folgt:

class User(Base):
    ...

class UserTag(Base):
    ...
    user = relationship("User", backref="tags")

Die Abfrage lautet wie folgt:

qry = session.query(User).filter(~User.tags.any(UserTag.tag.in_(tags))).order_by(User.id)
0
van 27 Nov. 2013 im 08:12

SQL wird so gehen

select u.* from user u join usertag ut on u.id = ut.user_id and ut.tag not in ('tag1', 'tag2');

Ich habe SQLAlchemy nicht verwendet, daher müssen Sie es in eine entsprechende SQLAlchemy-Abfrage konvertieren.

Ich hoffe es hilft.

Vielen Dank.

0
ms03 26 Nov. 2013 im 16:19