简体   繁体   English

SQL选择具有可互换值的两列的唯一组合

[英]SQL to select unique combination of two columns having interchangeable values

I have a flights table that has columns like "DEP" (departure) and "ARR" (arrival). 我有一个排班表,其中有“ DEP”(出发)和“ ARR”(到达)列。

It is obvious that Departure and arrival columns can have interchangeable city names. 很明显,出发和到达列可以具有可互换的城市名称。 For example, 1 row can have "SEA" as departure and "NYC" as arrival while another row can have "NYC" as departure and "SEA" as arrival. 例如,一行可以将“ SEA”作为出发点,将“ NYC”作为到达,而另一行可以将“ NYC”作为出发点并将“ SEA”作为到达。

I want to fetch only the unique combinations of departure and arrival cities. 我只想获取出发和到达城市的独特组合。 So, in this case, I want to see either of the 2 rows as output but not both the rows. 因此,在这种情况下,我想看到两行中的任何一行作为输出,而不是两行。

Here is how my table looks more realistically with data: 这是我的表格在数据中看起来更真实的样子:

CREATE TABLE flights(DEP CHAR(3), ARR CHAR(3), COST INT)

INSERT INTO flights VALUES ('SEA', 'CHG', 100)
INSERT INTO flights VALUES ('CHG', 'SEA', 100)
INSERT INTO flights VALUES ('SEA', 'SFO', 100)
INSERT INTO flights VALUES ('SEA', 'LSA', 100)
INSERT INTO flights VALUES ('SEA', 'SJO', 100)
INSERT INTO flights VALUES ('SFO', 'CHG', 100)
INSERT INTO flights VALUES ('SFO', 'SEA', 100)
INSERT INTO flights VALUES ('BOS', 'SEA', 100)
INSERT INTO flights VALUES ('NYC', 'CHG', 100)
INSERT INTO flights VALUES ('NYC', 'SEA', 100)
INSERT INTO flights VALUES ('SEA', 'NYC', 100)

SELECT * FROM flights --(11 rows)

DEP  ARR  COST
---- ---- ----
BOS  SEA  100
CHG  SEA  100
NYC  CHG  100
NYC  SEA  100
SEA  CHG  100
SEA  LSA  100
SEA  NYC  100
SEA  SFO  100
SEA  SJO  100
SFO  CHG  100
SFO  SEA  100

For above table my output should be like (8 rows): 对于上面的表,我的输出应该像(8行):

COL1 COL2 
---- ----
SFO  SEA
SFO  CHG
SEA  SJO
SEA  NYC
SEA  LSA
SEA  CHG
NYC  CHG
BOS  SEA

I was able to write a TSQL code using temp tables, variables, and loop etc but I strongly feel that this can be achieved in more simpler SQL probably by using UNION/INTERSECT/EXCEPT/EXISTS etc. 我能够使用临时表,变量和循环等编写TSQL代码,但我强烈感到可以通过使用UNION / INTERSECT / EXCEPT / EXISTS等在更简单的SQL中实现。

Here is my solution: 这是我的解决方案:

DECLARE @i INT = 1  --loop counter
DECLARE @exist BIT = 0  --flag to check if the combination  already exists
DECLARE @dep CHAR(3), @arr CHAR(3)

SELECT @i = COUNT(*) FROM dbo.flights   --get the row count

CREATE TABLE #tResult(dep CHAR(3), arr CHAR(3)) --output table
CREATE TABLE #tTemp (id TINYINT identity, dep CHAR(3), arr CHAR(3))

INSERT INTO #tTemp (dep, arr)
SELECT DISTINCT dep, arr FROM flights


WHILE (@i > 0)
BEGIN

    --get 
    SELECT @dep = dep, @arr = arr
    FROM #tTemp WHERE id = @i

    SET @exist = (SELECT count(*) FROM #tResult WHERE arr = @dep AND dep = @arr)    --check if this combination has been inserted in output

    --if not exists, insert this combination
    IF (@exist = 0)
    BEGIN
        INSERT INTO #tResult (dep, arr)
        VALUES (@dep, @arr)
    END

    SET @i = @i - 1 --decreament loop counter
END

SELECT * FROM #tResult

Can anyone please share a better or simpler solution to this problem. 任何人都可以对这个问题分享更好或更简单的解决方案。 Thanks! 谢谢!

One way is using UNION ALL : 一种方法是使用UNION ALL

select dep,
    arr
from flights
where dep < arr

union all

select dep,
    arr
from flights f
where dep > arr
    and not exists (
        select 1 from flights f2 
        where f.dep = f2.arr and f.arr = f2.dep
        );

Demo 演示版

Something like this usually works: 像这样的东西通常可以工作:

Select distinct case when dep < arr then dep else arr end as col1,
                case when dep < arr then arr else dep end as col2
From flights

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM