Я пытаюсь получить только одну из двух строк из следующей таблицы:

| fn1 |  o1  |  d1  |    date    | fn2 |  o2  |  d2  |
------------------------------------------------------
|  1  | ATL  | PEK  | 2018-09-29 |  7  | PEK  | ATL  |
|  7  | PEK  | ATL  | 2018-09-29 |  1  | ATL  | PEK  |

Я буду называть первую строку R1, а вторую - R2.

В общих случаях мне нужно проверить, что:

R1.fn1 = R2.dn2 И R1.fn2 = R2.fn1 И R1.o1 = R1.d2 = R2.d1 = R2.o1 И R1.d1 = R1.o2 = R2.o1 = R2.d2 И R1. date = R2.date

Если это верно для любых двух строк в моей таблице, мне нужно сгруппировать их только в одну. Я не знаю, есть ли способ решить эту проблему с помощью Group By или Distinct. Я пробовал несколько запросов, но в итоге так и не смог удалить избыточность.

Чтобы дать больше информации, я объясню, откуда взялась данная таблица. У меня есть следующая таблица:

CREATE TABLE flights (
flightNumber SERIAL PRIMARY KEY,
origin CHAR(3) REFERENCES airports(code),
destination CHAR(3) REFERENCES airports(code),
departureTime TIMESTAMP NOT NULL,
seatsNumber INT NOT NULL,
airlineAbv VARCHAR(10) REFERENCES airlines(abv));

Мне нужен запрос, чтобы проверить возможные поездки туда и обратно в тот же день. Для этого я использовал:

CREATE VIEW AtoB AS
SELECT flightNumber fN1, origin o1, destination d1, departureTime::DATE dT1
FROM flights;

CREATE VIEW BtoA AS
    SELECT flightNumber fN2, origin o2, destination d2, departureTime::DATE dT2
    FROM flights;

CREATE VIEW AtoBtoA AS
    SELECT * FROM AtoB, BtoA WHERE o1 = d2 AND o2 = d1 AND dT1 = dT2;

И из последнего запроса я получаю таблицу, очень похожую на ту, что в примере. Тот, что в примере, немного проще, чтобы было легче объяснить концепцию того, чего я хочу достичь.

Надеюсь, я прояснил свою проблему.

Ps: Здесь у вас вся моя база данных, чтобы увидеть дизайн. Думаю, это могло быть полезно.

CREATE TABLE airports (
    code CHAR(3) PRIMARY KEY,
    city VARCHAR(30) NOT NULL
);

CREATE TABLE airlines (
    name VARCHAR(30) NOT NULL,
    abv VARCHAR(10) PRIMARY KEY
);

CREATE TABLE passengers (
    id SERIAL PRIMARY KEY,
    name VARCHAR(60) NOT NULL
);

CREATE TABLE flights (
    flightNumber SERIAL PRIMARY KEY,
    origin CHAR(3) REFERENCES airports(code),
    destination CHAR(3) REFERENCES airports(code),
    departureTime TIMESTAMP NOT NULL,
    seatsNumber INT NOT NULL,
    airlineAbv VARCHAR(10) REFERENCES airlines(abv)
);

CREATE TABLE bookings (
    passengerId INT REFERENCES passengers(id),
    bookDate TIMESTAMP NOT NULL,
    price REAL NOT NULL,
    flightId INT REFERENCES flights(flightNumber)
);
0
Alejandro Jiménez Gutiérrez 5 Окт 2018 в 02:43

1 ответ

Лучший ответ

Я не уверен, какой у вас список таблиц. Однако для исходного вопроса вы можете использовать union all и not exists:

select t.*
from t
where fn1 < fn2 and o1 = d2 and d1 = o2 or
      (o1 <> d2 or d1 <> o2)
union all
select t.*
from t t2
where fn1 > fn2 and o1 = d2 and d1 = o2 and
      not exists (select 1
                  from t t2
                  where t2.fn1 = t.fn2 and t2.fn2 = t2.fn1 and
                        t2.o1 = t.d1 and t2.d1 = t.o1 and
                        t2.date = t.date
                 );
0
Gordon Linoff 5 Окт 2018 в 00:56