Улей удалить повторяющиеся типы отношений - PullRequest
0 голосов
/ 27 мая 2020

Я новый пользователь SQL и мне нужна ваша помощь! Я делаю анализ реляционного графа на основе базы данных SQL, которая является единственным ресурсом, который я могу использовать и у которого возникают проблемы с сохранением определенного типа отношений между двумя людьми .

У меня есть эта таблица:

+---------+----------------+--------+----------------+-----------+
| left_id | left_rel       | common | right_rel      | right_id  |
+---------+----------------+--------+----------------+-----------+
| Tom     | graduated_from | MIT    | worked_in      | Jerry     |
| Tom     | graduated_from | MIT    | graduated_from | Lee       |
| Lee     | graduated_from | MIT    | graduated_from | Tom       |
| Tom     | graduated_from | MIT    | graduated_from | Jerry     |
+---------+----------------+--------+----------------+-----------+

Мне нужна таблица, в которой идентичные отношения между двумя людьми сведены к одной единственной связи. Итак, отношения, в которых Том и Ли закончили Массачусетский технологический институт, имеют две записи, я хочу отбросить эти дубликаты. Я могу принять Тома как Left_id или Right_id, , только если его id и rel сопоставлены .

Надеюсь, этот фрагмент кода создания таблицы сэкономит вам время.

CREATE TABLE tmp (
      left_id varchar(20)
    , left_rel varchar(50)
    , common varchar(50)
    , right_rel varchar(50)
    , right_id varchar(20)
);
INSERT INTO tmp VALUES ("Tom", "graduated_from", "MIT", "worked_in", "Jerry");
INSERT INTO tmp VALUES ("Tom", "graduated_from", "MIT", "graduated_from", "Lee");
INSERT INTO tmp VALUES ("Lee", "graduated_from", "MIT", "graduated_from", "Tom");
INSERT INTO tmp VALUES ("Tom", "graduated_from", "MIT", "graduated_from", "Jerry");

То, что я пробовал до сих пор

CREATE TEMPORARY TABLE tmp1
AS 
SELECT 
        greatest(CONCAT_WS(':', left_id, left_rel), CONCAT_WS(':', right_id, right_rel)) AS Left_Part
      , Common
      , least(CONCAT_WS(':', left_id, left_rel), CONCAT_WS(':', right_id, right_rel)) AS Right_Part
  FROM tmp
;

CREATE TEMPORARY TABLE tmp2
AS 
SELECT 
        T1.Left_Part
      , T1.Common
      , T1.Right_Part
  FROM ( SELECT 
                 *
               , ROW_NUMBER() OVER(DISTRIBUTE BY Left_Part, Right_Part) AS rn
           FROM tmp1
        ) T1
 WHERE T1.rn = 1
;

CREATE TEMPORARY TABLE result
AS 
SELECT 
        SPLIT(Left_Part,':')[0] as left_id
      , SPLIT(Left_Part,':')[1] as left_rel
      , Common
      , SPLIT(Right_Part,':')[0] as right_id
      , SPLIT(Right_Part,':')[1] as right_rel
  FROM tmp2
;

дает результат

+---------+----------------+--------+----------------+-----------+
| left_id | left_rel       | common | right_rel      | right_id  |
+---------+----------------+--------+----------------+-----------+
| Tom     | graduated_from | MIT    | worked_in      | Jerry     |
| Tom     | graduated_from | MIT    | graduated_from | Lee       |
| Tom     | graduated_from | MIT    | graduated_from | Jerry     |
+---------+----------------+--------+----------------+-----------+

1 Ответ

0 голосов
/ 27 мая 2020

Кажется, вам нужно:

Common

id  name
1   MIT

RelationType

id rel_type
1  graduated_from 
2  worked_in

Person

id  name
1   Tom
2   Lee
3   Jerry

Relation

TypeId  PersonId CommonId
1       1        1
2       1        1
3       2        1

Данные получает

SELECT p1.name, rt1.rel_type, c.name, rt2.rel_type, p2.name
FROM Relation r1
JOIN Relation r2 ON r1.CommonId = r2.CommonId 
                AND r1.PersonId != r2.PersonId  -- or maybe '<'
JOIN Common c ON r1.CommonId = c.id
JOIN RelationType rt1 ON r1.TypeId = rt1.id
JOIN RelationType rt2 ON r2.TypeId = rt2.id
JOIN Person p1 ON r1.PersonId = p1.id
JOIN Person p1 ON r2.PersonId = p2.id

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...