sql >> Databasteknik >  >> RDS >> PostgreSQL

Gå med fyra bord som involverar LEFT JOIN utan dubbletter

Du har två LEFT JOINS :

  • Den första vänstra kopplingen kan anslutas till flera rader från solved . Säg, "jane" och "luke" löste uppgiften.
  • Den andra vänstra anslutningen kan bara gå med till användare som heter 'luke' ('luke' i anslutningsvillkoret!).

Du får fortfarande båda rader, 'jane' visas bara inte, kopplingsvillkoret filtrerar bort henne, men LEFT JOIN bevarar raden i resultatet ändå och lägger till NULL-värden.

Du kan uppnå det du är ute efter genom att använda parenteser och en [INNER] JOIN istället för LEFT JOIN mellan solved och users . Manualen:

Använd parenteser om det behövs för att bestämma häckningsordningen. I avsaknad av parentes, JOIN s bo från vänster till höger.

SELECT c.name AS cat_name, t.name AS task_name, u.name AS user_name
FROM   task t
JOIN   category c ON cat.id = t.category_id
LEFT   JOIN
      (solved s JOIN users u ON u.id = s.user_id AND u.name = 'luke') ON s.task_id = t.id
ORDER  BY 1, 2, 3;
  • Använder tabellnamnet users istället för det reserverade ordet users .

  • Förutsatt att users.name är definierad som unik eller så kan du ha flera användare som heter 'luke'.

  • Om (task.id, users.id) i solved är definierad som UNIQUE eller PRIMARY KEY , du behöver inte DISTINCT överhuvudtaget.

Den resulterande frågan är inte bara korrekt, utan också snabbare.

SqlAlchemy-versionen av ovanstående fråga: (bidraget av @van)
Detta förutsätter att Category , Task och User är mappade klasser, medan solved är en instans av Table (bara en associationstabell som visas i kodexempel Many to Many):

user_name = 'luke'
q = (session.query(Category.name, Task.name, User.name)
     .select_from(Task)
     .join(Category)
     .outerjoin(
         join(solved, User,
              (solved.c.user_id == User.id) & (User.name == user_name),
         ))
     .order_by(Category.name, Task.name, User.name)
     )


  1. java.sql.SQLException Parameterindex utanför intervallet (1> antal parametrar, vilket är 0)

  2. Att använda IS NULL eller IS NOT NULL på anslutningsvillkor - Teorifråga

  3. Genererar sql-kod programmatiskt

  4. PostgreSQL date() med tidszon