En utilisant SQLalchemy, je veux effectuer une jointure externe gauche et filtrer les lignes qui ont une correspondance dans la table jointe.Filtrage sur une jointure gauche dans SQLalchemy
J'envoie des notifications push, donc j'ai une table Notification
. Cela signifie que j'ai également une table ExpiredDeviceId
pour stocker device_ids qui ne sont plus valides. (Je ne veux pas simplement supprimer les notifications affectées que l'utilisateur pourrait plus tard réinstaller l'application, à quel point les notifications doivent reprendre selon les documents d'Apple.)
CREATE TABLE Notification (device_id TEXT, time DATETIME);
CREATE TABLE ExpiredDeviceId (device_id TEXT PRIMARY KEY, expiration_time DATETIME);
Note: il peut y avoir plusieurs Notifications par device_id. Il n'y a pas de table "Device" pour chaque périphérique.
Donc, en faisant SELECT FROM Notification
, je devrais filtrer en conséquence. Je peux le faire en SQL:
SELECT * FROM Notification
LEFT OUTER JOIN ExpiredDeviceId
ON Notification.device_id = ExpiredDeviceId.device_id
WHERE expiration_time IS NULL
Mais comment puis-je le faire dans SQLalchemy?
sess.query(
Notification,
ExpiredDeviceId
).outerjoin(
(ExpiredDeviceId, Notification.device_id == ExpiredDeviceId.device_id)
).filter(
???
)
Sinon je pourrais le faire avec une clause device_id NOT IN (SELECT device_id FROM ExpiredDeviceId)
, mais qui semble bien moins efficace.
Vous avez raison. J'ai incorrectement supposé que ExpiredDeviceId était en fait une référence d'objet, et que s'il n'y avait pas de ligne correspondante, ExpiredDeviceId lui-même serait None. Cependant, il s'agit en fait d'un nom de classe (table) et l'expression est compilée en SQL valide. (Notez que pour le libellé de ma question, je dois vérifier si * IS * None, ce qui fonctionne aussi.) –
Ah bon point, j'ai édité mon extrait de code pour éviter toute confusion –
'ExpiredDeviceId.expiration_time is None' ne sera pas work - il sera toujours évalué à False avant d'être passé à .filter(), provoquant un comportement inattendu (inattendu si vous vous attendez à lire la requête comme vous liriez SQL). Utilisez '=='. – Baczek