SQL - объединение таблиц, где первичный ключ в первой таблице является частью ключа во второй - PullRequest
2 голосов
/ 04 декабря 2009

Привет, я довольно новичок в SQL - так что будьте осторожны со мной!

В основном у меня есть две таблицы, к которым я пытаюсь присоединиться, где первичный ключ в первой таблице используется несколько раз во второй таблице (и образует первичный ключ во второй таблице вместе с другим столбцом)

Возможно, будет лучше, если я приведу пример:

Таблица 1: TravelRecords

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

Таблица 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

Для второй таблицы ключ представляет собой комбинацию TravelEventID и RemarkNo, которые вместе дают уникальный идентификатор.

По сути, все, что я пытаюсь сделать, это соединить таблицы вместе и вернуть локатор записей для бронирований, в которых текстовая строка примечания содержит LOWCOST BOOKING AND CREDIT CARD USED (поэтому в приведенном выше примере должны быть возвращены только ABC123 и DFD890.

Я пробовал что-то вроде:

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

Однако - это ничего не возвращает. Вероятно, это действительно очень просто - но я не могу заставить его вернуть требуемый ответ, когда я ищу один TravelEventID, содержащий оба поля Remark Text.

Любая помощь высоко ценится Приветствия

Ответы [ 6 ]

5 голосов
/ 04 декабря 2009

Наиболее читаемый способ проверить это, вероятно, двойной where exists, например:

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'
)

Альтернатива, которая может работать лучше, если использовать подзапрос inner join в качестве фильтра:

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

HAVING COUNT(DISTINCT RemarkText) = 2 гарантирует, что найдены оба типа замечаний.

2 голосов
/ 04 декабря 2009

В дополнение к логике Andomar IF EXISTS, другой способ, которым вы могли бы сделать это, было бы два присоединения к таблице замечаний:

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'

Однако в этом утверждении есть недостаток, заключающийся в том, что если у события путешествия есть два замечания с одним и тем же текстом, вы можете получить несколько строк с одним и тем же локатором записи.

2 голосов
/ 04 декабря 2009
WHERE   (TravelRecordRmks.RemarkText = 'LOWCOST BOOKING') 
        and (TravelRecordRmks.RemarkText = 'CREDIT CARD USED')

Похоже, вам нужно OR вместо AND.

Булева логика SQL (OR и AND) не интерпретируется так же, как повседневный английский.

1 голос
/ 04 декабря 2009

Вы не можете использовать and, например, для проверки значений, которые встречаются в нескольких строках. Лучшее, что вы можете сделать, это использовать or и count, чтобы убедиться, что вы соответствуете числу условий, которые вы хотите. Что-то вроде:

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
0 голосов
/ 04 декабря 2009

Проблема с вашим условием AND. Вы запрашиваете записи у TravelRecordRmks, в которых верно, что в поле RemarkText указано «LOWCOST BOOKING», а одновременно - «CREDIT CARD USED».

То, что вы хотите:

   WHERE RemarkText IN ('LOWCOST BOOKING', 'CREDIT CARD USED')

, который найдет строки, содержащие либо значение.

0 голосов
/ 04 декабря 2009

Попробуйте что-то вроде этого:

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
...