我有一张航空公司的桌子,上面有乘客识别器,他们的出发和到达目的地。
+-------------+-----------+----------+
| PassengerID | Town_from | Town_to |
+-------------+-----------+----------+
| 1 | London | Valetta |
| 1 | Valetta | London |
| 1 | Bangkok | Hanoi |
| 2 | Prague | Vienna |
| 2 | Vienna | Prague |
| 3 | Budapest | Vilnius |
| 4 | Moscow | Helsinki |
| 4 | Helsinki | Moscow |
| 4 | Moscow | Helsinki |
| 5 | Lyon | Paris |
| 5 | New York | Toronto |
+-------------+-----------+---------+
我想要做的是找到那些只在那里做过一条路线然后回来的乘客,所以结果应该是这样的:
+-------------+-----------+----------+
| PassengerID | Town_from | Town_to |
+-------------+-----------+----------+
| 2 | Prague | Vienna |
| 2 | Vienna | Prague |
| 4 | Moscow | Helsinki |
| 4 | Helsinki | Moscow |
| 4 | Moscow | Helsinki |
+-------------+-----------+---------+
或者像这样:
+-------------+
| PassengerID |
+-------------+
| 2 |
| 4 |
+-------------+
为什么这个PassengerID:
1 - 否,因为有1次回程和1次不回车
2 - 是因为只有1对
3 - 不,因为没有回程(Bud - Vil但不是Vil - Bud)
4 - 是因为虽然超过2次行程仍然有1对
5 - 否,因为这些对没有回程
我尝试过类似的事情:
SELECT PassengerID FROM table
GROUP BY PassengerID
HAVING COUNT(DISTINCT town_from) = 2 AND COUNT(DISTINCT town_to) = 2
但是,这也包括与结果集完全不同的目的地(ID 5)。我无法弄清楚如何在分组时比较2列。
答案 0 :(得分:2)
与SQL一样,有几种方法可以通过不同的查询获得相同的结果......我会发布我的。
这是工作的SQLfiddle:http://sqlfiddle.com/#!9/385d3/1
数据设置
create table travel(PassengerID varchar(64),Town_from varchar(64),Town_to varchar(64));
insert into travel values('1','London','Valetta');
insert into travel values('1','Valetta','London');
insert into travel values('1','Bangkok','Hanoi');
insert into travel values('2','Prague','Vienna');
insert into travel values('2','Vienna','Prague');
insert into travel values('3','Budapest','Vilnius');
insert into travel values('4','Moscow','Helsinki');
insert into travel values('4','Helsinki','Moscow');
insert into travel values('4','Moscow','Helsinki');
和实际查询
SELECT DISTINCT PassengerID
FROM TRAVEL
WHERE NOT EXISTS (
SELECT PassengerID
FROM TRAVEL a
WHERE TRAVEL.PassengerID = a.PassengerID AND NOT EXISTS
(SELECT *
FROM TRAVEL b
WHERE a.PassengerID = b.PassengerID
AND a.Town_from = b.Town_to
AND a.Town_to = b.Town_from
))
最里面的查询(FROM TRAVEL b
)查找与中间查询(FROM TRAVEL a
)相关的所有回程。
中间查询(FROM TRAVEL a
)然后使用NOT EXISTS
条款返回所有没有回程的旅行中的所有乘客的PassengerID。
外部查询再次反转结果,从初始表中删除这些“不匹配”的行程。
答案 1 :(得分:1)
DECLARE @FlightData TABLE (
PassengerID INT,
Town_from NVARCHAR(500),
Town_to NVARCHAR(500)
)
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 1,'London','Valetta'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 1,'Valetta','London'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 1,'Bangkok','Hanoi'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 2,'Prague','Vienna'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 2,'Vienna','Prague'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 3,'Budapest','Vilnius'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 4,'Moscow','Helsinki'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 4,'Helsinki','Moscow'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 4,'Moscow','Helsinki'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 5,'Lyon','Paris'
INSERT INTO @FlightData(PassengerID,Town_from,Town_to) SELECT 5,'New York','Toronto'
SELECT *
FROM @FlightData
WHERE PassengerID NOT IN(
SELECT
fd1.PassengerID
FROM @FlightData fd1
LEFT JOIN @FlightData fd2 ON fd2.PassengerID=fd1.PassengerID
AND fd2.Town_from=fd1.Town_to
AND fd2.Town_to=fd1.Town_from
WHERE fd2.PassengerID IS NULL
)
答案 2 :(得分:0)
你的数据和解释是模棱两可的,因为你消除了ID 1,因为它有两个不同的对(虽然一个是往返而一个不是),但你消除了ID 5,因为没有返回到一条腿的任何一条如果航班有回程,则表明将包括ID 5,但如果包括河内至曼谷航段则不会出现ID 1。
您是否只包含来自/来自单的ID(但多次出行都可以)?目前尚不清楚。
这是另一个能够产生你想要的ID 2和4结果的例子(但是如果那是你的意图,它不包括任何可能有多次完整和不同往返的ID)
SELECT DISTINCT(t1.id) FROM Travel t1 JOIN Travel t2 ON (t1.id=t2.id AND
t1.town_from=t2.town_to AND t1.town_from<>t2.town_from AND
t1.town_to<>t2.town_to)
EXCEPT
SELECT DISTINCT(t1.id) FROM Travel t1 JOIN Travel t2 ON (t1.id=t2.id AND
t1.town_from<>t2.town_to AND t1.town_from<>t2.town_from AND
t1.town_to<>t2.town_to)
第一个查询消除了ID 3(等等),因为它只选择至少有一个“往返”的ID。第二个查询查找所有具有非完整或不同行程的ID,并将其删除。
答案 3 :(得分:0)
另一种方式:
select distinct t1.PassengerID
from
travel t1
inner join travel t2
on t1.PassengerID = t2.PassengerID AND
t1.Town_from = t2.Town_to AND
t1.Town_to = t2.Town_from
where
(SELECT COUNT(*)
FROM (SELECT DISTINCT PassengerID, Town_from, Town_to
FROM travel t3
WHERE t3.PassengerID = t1.PassengerID) temp
) = 2
答案 4 :(得分:0)
WITH CTE AS
(
select distinct trv1.PassengerID,
trv1.town_from AS a,
trv1.town_to AS b,
trv2.town_from AS c,
trv2.town_to AS d
FROM travel trv1
LEFT JOIN travel trv2 ON trv1.PassengerID=trv2.PassengerID
AND trv1.town_from=trv2.town_to
AND trv1.town_to=trv2.town_from
ORDER BY trv1.PassengerID, trv1.town_from
),
SCTE AS
(
SELECT *, row_number() over(partition by CTE.PassengerID) AS count
FROM CTE
),
SSCTE AS
(
SELECT *, sum(SCTE.count) over(partition by SCTE.PassengerID) AS sum
FROM SCTE
)
SELECT
SSCTE.PassengerID,
SSCTE.a,
SSCTE.b
from SSCTE
WHERE SSCTE.sum = 3
ORDER BY SSCTE.PassengerID;