MySQL - создайте представление с ручным перекрестным соединением - PullRequest
0 голосов
/ 21 февраля 2019

Я пытаюсь создать представление с перекрестным соединением на основе нескольких условий if.

Я знаю, к какому столбцу и каким столбцам нужно присоединиться.

1 в таблице A с 1 и 2 в таблице B,

2 в таблице A с 1 и 3 в таблице B.

Я могусделать то же самое, создав таблицу сопоставления с этой логикой и использовать ее для объединения, но можно ли это сделать в самом определении представления, т. е. логика в определении представления?

Таблица A

ID | Animal
1  | Man
2  | Panda

Таблица B

ID | Fruit
1  | Bananna
2  | Apple
3  | Bamboo

Я хочу, чтобы в соответствии с известными условиями ожидалось бы следующее:

Просмотр

Man   | Bananna
Man   | Apple
Panda | Bananna
Panda | Bamboo

Ответы [ 4 ]

0 голосов
/ 21 февраля 2019

Вы, кажется, хотите:

select *
from a cross join
     b
where (a.id, b.id) in ( (1, 1), (1, 2), (2, 2), (2, 3) );

Я не уверен, если вы ищете более краткий способ написать это.

0 голосов
/ 21 февраля 2019
DROP TABLE IF EXISTS A;

CREATE TABLE A
(ID SERIAL PRIMARY KEY
,Animal VARCHAR(12) NOT NULL UNIQUE
);

INSERT INTO a VALUES
(1,'Man'),
(2,'Panda');

DROP TABLE IF EXISTS B;

CREATE TABLE B
(ID SERIAL PRIMARY KEY
,Fruit VARCHAR(12) NOT NULL UNIQUE
);

INSERT INTO b VALUES
(1,'Banana'),
(2,'Apple'),
(3,'Bamboo');

SELECT * 
  FROM a 
  JOIN b 
    ON (a.id = 1 AND b.id IN(1,2)) 
    OR (a.id = 2 AND b.id IN(1,3));
+----+--------+----+--------+
| ID | Animal | ID | Fruit  |
+----+--------+----+--------+
|  1 | Man    |  1 | Banana |
|  2 | Panda  |  1 | Banana |
|  1 | Man    |  2 | Apple  |
|  2 | Panda  |  3 | Bamboo |
+----+--------+----+--------+

Обратите внимание, что представления в MySQL практически не используются.

0 голосов
/ 21 февраля 2019

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

CREATE VIEW BadWay
AS
SELECT map.AID, a.Name AS AName, map.BID, b.Name AS BName
FROM TableA AS a
     INNER JOIN
     (   SELECT 1 AS AID, 1 AS BID UNION ALL
         SELECT 1 AS AID, 2 AS BID UNION ALL
         SELECT 2 AS AID, 1 AS BID UNION ALL
         SELECT 2 AS AID, 3 AS BID
     ) AS map
        ON map.AID = a.ID
     INNER JOIN TableB AS b
        ON b.ID = map.BID;

Я бы очень рекомендовал бы вам этого не делать.Если и когда вы хотите добавить, отредактировать или удалить сопоставления, гораздо проще сделать это путем вставки / обновления / удаления строк в таблице, чем изменить свое представление.

Вместо этого было бы лучше создать соединительную таблицу (Ассоциативная сущность) :

CREATE TABLE ABMapping 
(   
    AID INT NOT NULL, 
    BID INT NOT NULL
); 
INSERT INTO ABMapping (AID, BID) 
VALUES (1, 1), (1, 2), (2, 1), (2, 3);

Затем вы можете присоединиться к этому в своем представлении:

CREATE VIEW GoodWay
AS
SELECT  map.AID, a.Name AS AName, map.BID, b.Name AS BName
FROM    TableA AS a
        INNER JOIN ABMapping AS map
            ON map.AID = a.ID
        INNER JOIN TableB AS b
            ON b.ID = map.BID;

Примеры по БД <> Fiddle

0 голосов
/ 21 февраля 2019

Полагаю, вы могли бы сделать это: создать производную таблицу, используя ваши известные значения, и просто присоединиться к ней в качестве вашей соединительной / ассоциативной таблицы.Хотя вместо этого я бы сохранил это в таблице для большей гибкости и простоты обслуживания в долгосрочной перспективе.

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

SELECT A.Animal, B.Fruit
FROM A
INNER JOIN (SELECT 1 as Animal_ID,1  as Fruit_ID UNION ALL 
            SELECT 1, 2 UNION ALL 
            SELECT 2, 1 UNION ALL 
            SELECT 2,3) Derived
 on A.ID = Derived Animal_ID
INNER JOIN B 
 on Derived.Fruit_ID = B.ID

Если вам нужно сохранить перекрестное объединение (низкая производительность на больших таблицах), тогда это может сработать ...

SELECT A.Animal B.Fruit
FROM A
CROSS JOIN B
WHERE not exists (SELECT 1 
                  FROM (SELECT 1 as Animal_ID,1  as Fruit_ID UNION ALL 
                        SELECT 1, 2 UNION ALL 
                        SELECT 2, 1 UNION ALL 
                        SELECT 2,3) Derived
                  WHERE A.ID = Derived.Animal_ID
                   and  B.ID = Derived.Fruit_ID)

Однако вам может быть лучше хранить количества, которые не совпадают, в зависимости от объёмов таблицы с течением времени.

Оба эти подхода подходят к значениям HARD CODE.Как правило, это первый признак того, что разработчик делает что-то не так.В очень редких случаях значения должны быть жестко закодированы;вместо этого сохраните их как переменные в таблице, что обеспечивает гибкость изменений без изменений кода.

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