2016-11-07 2 views
1

je dois gauche se joindre à deux tables avec une condition where:Postgres gauche Joignez-vous à condition where

time_table
id  rid  start_date    end_date 
1  2  2017-07-01 00:00:00  2018-11-01 00:00:00 
2  5  2017-01-01 00:00:00  2017-06-01 00:00:00 
3  2  2018-07-01 00:00:00  2020-11-01 00:00:00 
record_table
id  name     date 
1  record1  2017-10-01 00:00:00 
2  record2  2017-02-01 00:00:00 
3  record3  2017-10-01 00:00:00 

Je dois obtenir tous les documents qui sont présents en date donnée gamme. Dans l'exemple ci-dessus, j'ai besoin de ces enregistrements qui se trouvent sous rid = 2 seulement. D'où la sortie de la requête ci-dessus doit être:

1  record1  2017-10-01 00:00:00  
3  record3  2017-10-01 00:00:00 
+1

Qu'avez-vous essayé? S'il vous plaît poster quelques exemples de code et de sortie, et dites-nous ce qui ne fonctionne pas pour vous. En outre, vérifiez ce lien: stackoverflow.com/help/mcve. – CGritton

+1

utilisez-vous postgresql ou mysql? – chresse

+0

Votre exemple de sortie ne nécessite pas de jointure externe comme dans le titre de la question. C'est une jointure interne. –

Répondre

1

gauche se joindre deux tables avec un état où

Il y a un piège vous attend ici. Lors de l'utilisation d'un LEFT [OUTER] JOIN, il est généralement mauvais pour filtrer avec une condition WHERE, annulant ainsi la fonctionnalité spéciale d'un LEFT JOIN pour inclure toutes les lignes de la table gauche inconditionnellement. Explication détaillée:

Alors, mettez les conditions dans la clause WHERE qui sont censés filtrer toutes les lignes (rid = 2), mais rendre les conditions de gauche se joindre à des lignes de record_table à être rejoindre réelle conditions:

SELECT t.start_date, t.end_date -- adding those 
    , r.id, r.name, r.date 
FROM time_table t 
LEFT JOIN record_table r ON r.date >= t.start_date 
          AND r.date < t.end_date 
WHERE t.rid = 2; 

As commented, il est logique d'inclure des colonnes de time_table dans le résultat, mais c'est mon option supp ion. Vous devez également être très clair à propos de limites supérieure et inférieure. La convention générale est de inclure inférieure et exclure les plages de limite supérieure dans le temps (timestamp). D'où mon utilisation de >= et < ci-dessus.

connexes:

performance devrait être aucun problème avec les index droit. Vous avez besoin d'un index (ou PK) sur time_table sur (rid) et un autre sur record_table sur (date).

1
SELECT time_tbl.name,record_tbl.date 
FROM dbo.time_table AS time_tbl 
    INNER JOIN record_table AS record_tbl 
      ON time_tbl.id=record_tbl.id 
WHERE(time_tbl.rid=2)  
+4

Ceci est incorrect dans presque tous les aspects. Erreur JOIN, condition incorrecte, colonnes de résultats erronées. Cela peut arriver, mais surtout: pas d'explication du tout. –

0

Je ne suis pas sûr que ce soit ce que vous voulez, mais si vous dites que vous voulez que les dates où la date est record_table entre la les dates du time_table, alors ce serait faire le travail:

select 
    rt.id, rt.name, rt.date 
from 
    time_table tt 
    join record_table rt on 
    rt.date between tt.start_date and tt.end_date 
where 
    tt.rid = 2 

cela dit, ce sera terriblement inefficace pour les grands ensembles de données. Si vos données sont relativement petites (< 10k enregistrements dans chaque tableau, post-filtres), alors cela n'aura probablement pas beaucoup d'importance, mais si vous deviez mettre à l'échelle ce concept, il vous faudrait en savoir plus sur vos données - par exemple , faites les dates, toujours arrondies au premier de chaque mois? Encore une fois, d'après votre exemple, je ne savais pas si c'était ce que vous vouliez dire par «obtenir tous les enregistrements qui sont présents dans une période donnée».