在主表中查找与SQL Server中另一个表中的记录匹配的记录

时间:2015-06-16 20:06:00

标签: sql sql-server sql-server-2012

我有一个包含三个表的SQL Server数据库: Trips 切片 Legs

每次旅行切片有一对多的关系,而切片 Legs 。

Trips表示完整行程,切片仅表示行程的出站或返回部分,而行表示出站或返回切片中的所有停靠点。

我希望能够找到匹配腿的所有旅程。

以下是表格:

行程

__atomic_add_fetch

tripId  saleTotal   queryDate
1       $200            6/10/2015
2       $198            6/11/2015

sliceId     connections duration    tripIdFK
1           1           50          1 
2           1           45          1 
3           0           60          2 
4           1           85          2 

我如何能够通过搜索departureAirport / arrivalAirport(JFK / FRA)找到所有航空公司和航班号匹配的所有航班,例如legId 1-4?

换句话说,legId 1-4是一个单元,其中Trip 1和legId 5-7的详细信息是另一个单元,其中包含Trip 2的详细信息。我需要查找哪些其他行程完全匹配legId 1-4详细信息(除了PK和FK)等。任何帮助将不胜感激!!

3 个答案:

答案 0 :(得分:2)

希望这有帮助。

只需传递要与之比较其他记录的基本TripId(在@BaseTripID中)。我假设您只关心航空公司,flightNumber,departureAirport,ArrivalAirport,与任何其他旅行完全匹配,无论日期字段如何。

create table Trips(tripId int,saleTotal int,queryDate date)
create table Slices(sliceId int ,connections int,duration int ,tripIdFK int)
create table Legs(legId int, carrier char(2), flightNumber int, departureAirport char(3), departureDate date, ArrivalAirport char(3), ArrivalDate date, sliceIDFK int)


insert into Trips values(1,200,'6/10/2015'),(2,198,'6/11/2015'),(3,300,'6/15/2015'),(4,200,'6/21/2015')
insert into Slices values(1,1,50,1),(2,1,45,1),(3,0,60,2),(4,1,85,2),(5,1,50,3),(6,1,45,3),(7,1,45,4),(8,1,45,4)
insert into Legs values(1,'AA',1,'JFK','7/1/2015','LON','7/2/2015',1) ,
(2,'AA',2,'LON','7/2/2015','FRA','7/2/2015',1),
(3,'AA',11,'FRA','7/10/2015','LON','7/10/2015',2),
(4,'AA',12,'LON','7/10/2015','JFK','7/10/2015',2),
(5,'UA',5,'EWR','8/1/2015','LAX','8/1/2015',3),
(6,'UA',6,'LAX','8/5/2015','ORD','8/5/2015',4),
(7,'UA',7,'ORD','8/5/2015','EWR','8/5/2015',4),
(8,'AA',1,'JFK','7/11/2015','LON','7/12/2015',5),
(9,'AA',2,'LON','7/12/2015','FRA','7/12/2015',5),
(10,'AA',11,'FRA','7/20/2015','LON','7/20/2015',6),
(11,'AA',12,'LON','7/20/2015','JFK','7/20/2015',6),
(12,'AA',1,'JFK','7/1/2015','LON','7/2/2015',7) ,
(13,'AA',2,'LON','7/2/2015','FRA','7/2/2015',7),
(14,'AA',11,'FRA','7/10/2015','BEL','7/10/2015',8),
(15,'AA',12,'BEL','7/10/2015','JFK','7/10/2015',8)

--select * from  Trips
--select * from  Slices
--select * from  Legs

-------------------------------------------------------------------

Declare @BaseTripID int = 1, @Legs int ,@MatchingTripID int

declare @BaseTrip table(carrier char(2), flightNumber int, departureAirport char(3), ArrivalAirport char(3),row_no int)
declare @MatchingTrip table(carrier char(2), flightNumber int, departureAirport char(3), ArrivalAirport char(3),row_no int,legid int,tripid int)


insert into @BaseTrip
select carrier, flightNumber, departureAirport, ArrivalAirport,ROW_NUMBER() over(order by l.legId) 
from Legs l join slices s on s.sliceId = l.sliceIDFK
where s.tripIdFK = @BaseTripID


select @Legs=count(*) from @BaseTrip


Insert into @MatchingTrip
select carrier, flightNumber, departureAirport, ArrivalAirport,ROW_NUMBER() over(partition by s.tripIdFK order by l.legId) as row_no,l.legId,s.tripIdFK
from Legs l join slices s on s.sliceId = l.sliceIDFK
and s.tripIdFK in 
(select s.tripIdFK
from Legs l join slices s on s.sliceId = l.sliceIDFK
and s.tripIdFK <> @BaseTripID
Group by s.tripIdFK having count(l.legId)=@Legs)


select @MatchingTripID = m.tripid
from @MatchingTrip m join @BaseTrip b 
on m.carrier = b.carrier
and m.flightNumber = b.flightNumber
and m.departureAirport = b.departureAirport
and m.ArrivalAirport = b.ArrivalAirport
and m.row_no = b.row_no
GROUP BY m.tripid HAVING COUNT(*) = @Legs


select s.tripIdFK as matchingTripID,l.legid,l.carrier,l.flightNumber,l.departureAirport,l.ArrivalAirport  
from Legs l 
join Slices s on s.sliceId = l.sliceIDFK
where s.tripIdFK = @MatchingTripID


---------------------
drop table Trips
drop table Slices
drop table Legs

利用腿部计数是关键。因此,除了完全相同的腿之外,我们正在消除任何匹配(只有两条匹配腿的行程4)。所以现在我们只获得Trip 3作为匹配记录。

请注意,我们也排除了旅行,除了匹配的旅行之外还有任何额外的航程。我希望这是你所期待的,一对完全相同的旅程。

答案 1 :(得分:1)

噢,我的大脑疼!...

将所有问号(其中3个)替换为您要检查类似行程的行程ID。

select distinct s.tripIDFK as tripId
from Legs l
left join Slices s on l.sliceIDFK = s.sliceId
where s.tripIDFK != ?
and not exists (
  select carrier, flightNumber, departureAirport, departureDate
  from Legs l2
  left join Slices s2 on l2.sliceIDFK = s2.sliceId
  where s2.tripIDFK = s.tripIDFK
  except
  select carrier, flightNumber, departureAirport, departureDate
  from Legs l2
  left join Slices s2 on l2.sliceIDFK = s2.sliceId
  where s2.tripIDFK = ?
)
and not exists (
  select carrier, flightNumber, departureAirport, departureDate
  from Legs l2
  left join Slices s2 on l2.sliceIDFK = s2.sliceId
  where s2.tripIDFK = ?
  except
  select carrier, flightNumber, departureAirport, departureDate
  from Legs l2
  left join Slices s2 on l2.sliceIDFK = s2.sliceId
  where s2.tripIDFK = s.tripIDFK
)
order by s.tripIDFK

查询的内容是and not exists子句。他们获得一次旅行的腿部数据,并使用except子句有效地减去另一次旅行的腿部数据。如果您没有任何东西,则第二行程数据包含所有第一行程数据。您必须运行and not exists子句两次(操作数反转)以确保两组行程数据真正相同,并且一个不仅仅是另一组的子集。

这绝不可扩展到大量行。

答案 2 :(得分:0)

另一种方法是确定/存储每个切片的legsKey,这样您就可以在不同的行程中找到匹配的切片。

对于每个切片,您的legsKey是附加的每个腿的载体和航班号,您可以使用For XML Path来执行此操作,例如this

类似的东西:

select
   distinct  
    stuff((
        select ',' + l.carrier + ':' + l.flightNumber
        from legs l
        where l.carrier = carrier and l.flightnumber = flightnumber
        order by l.carrier, l.flightnumber
        for xml path('')
    ),1,1,'') as legsList
from legs
group by carrier, flightnumber