考虑下面的表结构和数据
CREATE TABLE Distance(
source VARCHAR(20),
destination VARCHAR(20),
distance INTEGER
);
Select * from Distance;
source destination distance
======= =========== ======
Chennai Mumbai 500
Mumbai Chennai 500
Mumbai Bangalore 500
Bangalore Mumbai 500
Goa Mumbai 100
Mumbai Goa 100
Kolkata Goa 1000
如果重复,我需要输出有 2 个城市的单个记录,即以下 2 个城市中的任何一个记录都可以。
Chennai Mumbai 500
Mumbai Chennai 500
Expected o/p:
source destination distance
======= =========== ======
Chennai Mumbai 500
Mumbai Bangalore 500
Goa Mumbai 100
Kolkata Goa 1000
这是一种使用
least()
和 greatest()
的方法:
select least(source, destination), greatest(source, destination), max(distance)
from distance
group by least(source, destination), greatest(source, destination);
这有一个缺点,您可能会返回不在表中的行。例如,如果您有一行包含“Mumbai/Chennai/500”,则此查询将返回“Chennai/Mumbai/500”——并且该行不在原始表中。
所以,另一种方法是:
select source, destination, distance
from distance
where source < destination
union all
select destination, source, distance
from distance d
where source > destination and
not exists (select 1
from distance d2
where d2.source = d.destination and d2.destination = d.source
);
此版本还兼容 ANSI,并且应该适用于所有数据库。
如果您需要保留您可能使用的列的顺序
SELECT *
FROM Distance t1
WHERE NOT EXISTS
(
SELECT * FROM Distance t2
WHERE t1.destination = t2.source
AND t1.source = t2.destination
AND t1.destination > t2.destination
);
当每个
source/combination
存在多行时,您必须添加 DISTINCT
或 GROUP BY
。
SELECT DISTINCT LEAST(source,destination) a
, GREATEST(source,destination) b
, distance
FROM distance;
select
(case when source>destination then source else destination end) as src,
(case when source<destination then source else destination end) as dstn,
distance from distance
下面的逻辑看起来更容易理解,并且做同样的工作。
select a.source,a.destination,a.distance as distance from
distance a join distance b on a.destination = b.source and b.destination = a.source
and a.source < b.source
union all
select a.source,a.destination,a.distance from distance a left join distance b
on a.destination = b.source and b.destination = a.source
where b.source is NULL ;
cte 为 (
选择 *,CASE WHEN 来源
cte_rn 为 ( select *,ROW_NUMBER () over(按梳排序按梳分区) as rn 来自 cte)
选择出发地、目的地、距离 cte_rn 其中 rn=1 按来源排序