2 votes

SQL - Jointure de tables où la clé primaire de la première table fait partie de la clé de la deuxième table

Bonjour, je suis relativement nouveau dans le domaine de SQL - alors soyez gentil avec moi !

J'ai essentiellement deux tables que j'essaie de joindre et dans lesquelles la clé primaire de la première table est utilisée plusieurs fois dans la seconde (et forme la clé primaire de la seconde table avec une autre colonne).

Il est probablement préférable que je donne un exemple :

Tableau 1 : TravelRecords

TravelEventID  EventType  RecordLocator  OfficeID    
 0001            F          ABC123         LDN  
 0002            F          ABC234         LDN  
 0003            T          BDF232         SOU  
 0004            F          DFD890         GLA  

Tableau 2 : TravelRecordRmks

TravelEventID  RemarkNo    Keyword       Text  
 0001            1           TVL          LOWCOST BOOKING  
 0001            2           TVL          CREDIT CARD USED  
 0001            3           PSG          COST CENTRE REQUIRED  
 0001            4           PSG          EMPLOYEE NUM REQUIRED
 0002            1           TVL          CREDIT CARD USED
 0002            2           AGT          BOOKED BY AGENT
 0002            3           AGT          CONFIRM WITH AIRLINE
 0002            4           TVL          LOWEST FARE CONFIRMED
 0002            5           TVL          NO CANCELLATION CHARGE
 0003            1           TVL          LOWCOST BOOKING
 0003            2           TVL          CARRIER : EASYJET
 0003            3           TVL          LOWEST FARE CONFIRMED
 0004            1           TVL          LOWCOST BOOKING
 0004            2           TVL          CREDIT CARD USED

Pour la deuxième table, la clé est la combinaison du TravelEventID et du RemarkNo qui, combinés, donnent un identifiant unique.

En fait, tout ce que j'essaie de faire, c'est de joindre les tables ensemble et de renvoyer le localisateur d'enregistrement pour les réservations dont la ligne de texte de remarque est RÉSERVATION À BAS PRIX ET CARTE DE CRÉDIT UTILISÉE (donc, dans l'exemple ci-dessus, seuls ABC123 et DFD890 devraient être renvoyés).

J'ai essayé quelque chose du genre :

SELECT  TravelRecords.RecordLocator
FROM    TravelRecords INNER JOIN
        TravelRecordRmks ON TravelRecords.TravelEventID = TravelRecordRmks.TravelEventID db  
WHERE   (TravelRecordRmks.RemarkText = 'LOWCOST BOOKING') 
        and (TravelRecordRmks.RemarkText = 'CREDIT CARD USED')
ORDER BY dbo.vw_gTravelOrderEvent.RecordLocator

Cependant - cela ne donne rien. C'est probablement très simple, mais je n'arrive pas à obtenir la réponse requise lorsque je cherche à ce que l'unique TravelEventID contienne les deux champs Remark Text.

Toute aide est la bienvenue. Cheers

5voto

Andomar Points 115404

La façon la plus lisible de vérifier ceci est probablement un double where exists comme :

SELECT  tr.*
FROM    TravelRecords tr
WHERE EXISTS (
    SELECT * FROM TravelRecordRmks trr 
    WHERE trr.TravelEventID = tr.TravelEventID
    AND trr.RemarkText = 'LOWCOST BOOKING'
)
AND EXISTS (
    SELECT * FROM TravelRecordRmks trr 
    WHERE trr.TravelEventID = tr.TravelEventID
    AND trr.RemarkText = 'CREDIT CARD USED'
)

Une alternative qui pourrait être plus performante, en utilisant un inner join sous-requête comme un filtre :

SELECT  tr.*
FROM    TravelRecords tr
INNER JOIN (
        SELECT TravelEventID
        FROM TravelRecordRmks trr 
        WHERE RemarkText IN ('CREDIT CARD USED','LOWCOST BOOKING')
        GROUP BY TravelEventID
        HAVING COUNT(DISTINCT RemarkText) = 2
) filter 
ON      filter.TravelEventID = tr.TravelEventID

En HAVING COUNT(DISTINCT RemarkText) = 2 s'assure que les deux types de remarques sont trouvés.

2voto

JasDev Points 358
WHERE   (TravelRecordRmks.RemarkText = 'LOWCOST BOOKING') 
        and (TravelRecordRmks.RemarkText = 'CREDIT CARD USED')

On dirait que vous avez besoin OR au lieu de AND .

La logique booléenne du SQL (OU et ET) n'est pas interprétée de la même manière que l'anglais courant.

2voto

Tom H. Points 23783

En plus de la logique IF EXISTS d'Andomar, une autre façon de procéder serait de joindre deux fois la table des remarques :

SELECT
     TR.record_locator,
FROM
     Travel_Records TR
INNER JOIN Travel_Record_Remarks TRR1 ON
     TRR1.travel_event_id = TR.travel_event_id AND
     TRR1.remark_text = 'LOWCOST BOOKING'
INNER JOIN Travel_Record_Remarks TRR2 ON
     TRR2.travel_event_id = TR.travel_event_id AND
     TRR2.remark_text = 'CREDIT CARD USED'

Il y a cependant un défaut avec cette déclaration, qui est que si un événement de voyage a deux remarques avec le même texte, vous pourriez obtenir plusieurs lignes avec le même localisateur d'enregistrement.

1voto

Donnie Points 17312

Vous ne pouvez pas utiliser un and comme ça, pour vérifier les valeurs qui apparaissent sur plusieurs lignes. Le mieux que vous puissiez faire est d'utiliser un or y count pour vous assurer que vous faites correspondre le nombre de conditions que vous voulez. Quelque chose comme :

select
  tr.RecordLocator
from
  TravelRecords tr
  join (
    select 
      r.TravelEventID,
      count(*)
    from
      TravelRecords r
      join TravelRecordRmks rr on r.TravelEventID = rr.TravelEventID
    where
      rr.Text = 'LOWCOST BOOKING' or rr.Text = 'CREDIT CARD USED'
    group by
      r.TravelEventID
    having
      count(*) = 2   -- must match both (or have one of them twice) for a single TravelEventID
  ) x on x.TravelEventID = tr.TravelEventID
order by
  tr.RecordLocator

0voto

TLiebe Points 6433

Essayez quelque chose comme ça :

SELECT DISTINCT
  tr.RecordLocator
FROM
  TravelRecords tr
  INNER JOIN TravelRecordRmks rmk
    ON tr.TravelEventID = rmk.TravelEventID
WHERE
  rmk.RemarkText = 'LOWCOST BOOKING'
  OR rmk.RemarkText = 'CREDIT CARD USED'
ORDER BY
  tr.RecordLocator

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X