Anu*_*thi 4 sql t-sql database sql-server
我有一个航班表,其中包含“DEP”(出发)和“ARR”(到达)等列。
很明显,出发和到达列可以具有可互换的城市名称。例如,一行可以将“SEA”作为出发,“NYC”作为到达,而另一行可以将“NYC”作为出发,“SEA”作为到达。
我只想获取出发和到达城市的独特组合。因此,在这种情况下,我希望将 2 行中的任何一行都视为输出,而不是两行。
以下是我的表格如何用数据看起来更真实:
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
Run Code Online (Sandbox Code Playgroud)
对于上表,我的输出应该是(8 行):
COL1 COL2
---- ----
SFO SEA
SFO CHG
SEA SJO
SEA NYC
SEA LSA
SEA CHG
NYC CHG
BOS SEA
Run Code Online (Sandbox Code Playgroud)
我能够使用临时表、变量和循环等编写 TSQL 代码,但我强烈认为这可以通过使用 UNION/INTERSECT/EXCEPT/EXISTS 等在更简单的 SQL 中实现。
这是我的解决方案:
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
Run Code Online (Sandbox Code Playgroud)
任何人都可以分享一个更好或更简单的解决方案来解决这个问题。谢谢!
像这样的事情通常有效:
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
Run Code Online (Sandbox Code Playgroud)
一种方法是使用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
);
Run Code Online (Sandbox Code Playgroud)