这个sql复杂面试问题的解决方案是什么?

这个sql复杂面试问题的解决方案是什么?,sql,Sql,我很擅长sql。 我在面试中遇到过这个问题,无法找到答案 问题: 有一个位置表 有3列(源、目标、距离),如下所示 地点: Source - Destination - Distance Hyderabad - Chennai - 700 Chennai - Hyderabad - 700 Hyderabad - Bangalore -650 Source - Destination - Distance Hyderabad - Chennai - 700 Hyderabad - Bangal

我很擅长sql。 我在面试中遇到过这个问题,无法找到答案

问题: 有一个位置表 有3列(源、目标、距离),如下所示

地点:

Source - Destination - Distance
Hyderabad - Chennai - 700
Chennai - Hyderabad - 700
Hyderabad - Bangalore -650
Source - Destination - Distance
Hyderabad - Chennai - 700
Hyderabad - Bangalore -650
如上所述,海得拉巴到钦奈或钦奈到海得拉巴都意味着相同的距离将始终相同

因此,我们需要将查询写入,以便输出不应有此类重复记录

在上述情况下,输出应为

地点:

Source - Destination - Distance
Hyderabad - Chennai - 700
Chennai - Hyderabad - 700
Hyderabad - Bangalore -650
Source - Destination - Distance
Hyderabad - Chennai - 700
Hyderabad - Bangalore -650

我认为在这些条件下,这就是你想要的:

select l.*
from location l
where l.source < l.destination;
选择l*
从位置l
其中,l.源
戈登·林诺夫(Gordon Linoff)有一个很好的简洁答案,但我唯一的批评是,只有在任意两个位置的表中都有两个方向的记录时,这种方法才能可靠地工作。如果这是你过去旅行过的腿的集合,并且只从海得拉巴>班加罗尔旅行过,但从未回程(根据提供的数据),你将不会得到这对腿的结果。在OP的问题中,不清楚这是否是一个考虑因素

到目前为止,问题或任何答案中未提及的另一个考虑因素是,如果往返行程的两段(无论出于何种原因)具有不同的值,会发生什么情况。这是可以想象的,与其他答案将导致重复

这应该能更可靠地工作(感谢《代码》作者David•••••וMarkovitz对《代码》的评论):

选择case when l.sourcel.destination然后l.source else l.destination结束为destination时的情况,
最大(l.距离)距离
从位置l
分组
当l.sourcel.destination然后l.source else l.destination end时的情况

如果您的SQL DB/engine支持最小/最大语法(这是一种ISO语法,很多语法都支持):



如果没有:

select  distinct
        case when source < destination then source else destination end as source
       ,case when source < destination then destination else source end as destination
       ,distance

from    location
选择distinct
当source


这是一个很好的讨论,@pcdev的解决方案很好。我能做的改进是,在没有回程的情况下,保持原始来源和目的地完好无损

在pcdev的示例中,如果您得到这样的记录

C --> B
A --> D
D --> A
输出将是

B --> C (The original order is not preserved) 
A --> D 

create table location ( Source nvarchar(max), Destination nvarchar(max), Distance int)

insert into location values
('Hyderabad', 'Chennai',   700),
('Chennai',   'Hyderabad', 700),
('Hyderabad', 'Bangalore', 650),
('Cochin', 'Bangalore', 650),
('Hyderabad', 'England', 650),
('England', 'Hyderabad', 650)

select * from (
select l.source
       ,l.destination
       ,case when l.source < l.destination then l.source else l.destination end as source_col
       ,case when l.source > l.destination then l.source else l.destination end as destination_col
       ,row_number() over(partition by case when l.source < l.destination then l.source else l.destination end
                                       ,case when l.source > l.destination then l.source else l.destination end
                           order by l.source) as rnk
from location l
)x
where x.rnk=1

+-----------+-------------+------------+-----------------+-----+
|  source   | destination | source_col | destination_col | rnk |
+-----------+-------------+------------+-----------------+-----+
| Cochin    | Bangalore   | Bangalore  | Cochin          |   1 |
| Hyderabad | Bangalore   | Bangalore  | Hyderabad       |   1 |
| Chennai   | Hyderabad   | Chennai    | Hyderabad       |   1 |
| England   | Hyderabad   | England    | Hyderabad       |   1 |
+-----------+-------------+------------+-----------------+-----+
B-->C(不保留原始顺序)
A-->D
创建表位置(源nvarchar(最大)、目标nvarchar(最大)、距离int)
插入到位置值中
(‘海得拉巴’、‘钦奈’、700),
(“钦奈”、“海得拉巴”,700),
(‘海得拉巴’、‘班加罗尔’、650),
('Cochin','Bangalore',650),
(‘海得拉巴’、‘英格兰’、650),
(‘英格兰’、‘海得拉巴’、650)
从中选择*(
选择l.source
,l.目的地
,当l.sourcel.destination,然后l.source else l.destination结束为destination\u col时的情况
,row_number()(当l.sourcel.destination然后l.source else l.destination end时的情况
按l.来源订购)作为rnk
从位置l
)x
其中x.rnk=1
+-----------+-------------+------------+-----------------+-----+
|源|目的地|源|列|目的地|列| rnk|
+-----------+-------------+------------+-----------------+-----+
|科钦|班加罗尔|班加罗尔|科钦| 1|
|海得拉巴|班加罗尔|班加罗尔|海得拉巴| 1|
|钦奈|海得拉巴|钦奈|海得拉巴| 1|
|英格兰|海得拉巴|英格兰|海得拉巴| 1|
+-----------+-------------+------------+-----------------+-----+
小提琴链接

正如pcdev在其回答中指出的那样:“我唯一的批评是,只有在任何两个位置的表中都有两个方向的记录时,这种方法才能可靠地工作。”。只需留下此友好评论,您就可以收到通知。:)绝对比它第一次出现时更复杂+1您了解问题的实质,但您的语法有问题。如果使用GROUP BY,则它应位于大小写表达式上,而不是原始列上。但是,一个简单的区别就可以了。GROUP BY的功能与您预期的不同,
海得拉巴-钦奈
钦奈-海得拉巴
将不在同一组中。谢谢@DavidדדווMarkovitz,你说得对-谢谢!现在修复并添加一些解释…@DavidדדווMarkovitz为了回应您的评论“简单的不同就可以了”,我试图解决通过聚合来区分距离的问题。
group by
不用于重复消除。请参阅上面编辑的答案,我认为在最有可能的输入数据下,该答案最为有效。现在,您已经拥有了正确的组,不需要使用不同的组