SQL - 表连接,其中第一个表中的主键是第二个键中的键的一部分

时间:2009-12-04 14:39:41

标签: sql primary-key

嗨,我对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的组合,它们组合在一起给出了唯一的ID。

基本上我所要做的就是将表连在一起并返回记录定位器,以便使用注释文本行使用LOWCOST BOOKING和CREDIT CARD(因此在上面的示例中,只应返回ABC123和DFD890。 / p>

我尝试过以下方面:

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时,我无法让它返回所需的响应。

任何帮助非常感谢 干杯

6 个答案:

答案 0 :(得分:5)

检查这个问题最可读的方法可能是双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确保找到两种类型的评论。

答案 1 :(得分:2)

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

您似乎需要OR而不是AND

SQL布尔逻辑(OR和AND)的解释方式与日常英语不同。

答案 2 :(得分:2)

除了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'

但是这个陈述存在一个缺陷,即如果旅行事件有两个具有相同文本的备注,那么最终可能会使用相同的记录定位器返回多行。

答案 3 :(得分:1)

您不能使用and之类的内容来检查多行上发生的值。您可以做的最好的事情是使用orcount来确保符合您想要的条件数量。类似的东西:

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

答案 4 :(得分:0)

尝试这样的事情:

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

答案 5 :(得分:0)

问题在于你的状况。您要求TravelRecordRmks提供记录,其中RemarkText字段为'LOWCOST BOOKING'且同时是'CREDIT CARD USED'。

你想要的是:

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

将找到包含 值的行。