MySQL-使用手动交叉联接创建视图

时间:2019-02-21 15:57:23

标签: mysql sql

我正在尝试基于多个if条件创建具有交叉联接的视图。

我知道哪一列要与哪些列连接。

  

表A中的1和表B中的1和2,

     

表A中的2,表B中的1和3。

我可以通过使用此逻辑创建映射表并将其用于联接来完成相同的工作,但是可以在视图定义本身中完成,即逻辑是否在视图定义中?

表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 :(得分:1)

我想您可以这样做:使用您的已知值创建一个派生表,然后简单地将其连接为结点/关联表。虽然我可以将其存储在表中,但是可以更大的灵活性并易于长期维护。

注意:这种方法消除了交叉连接的需要。您可以进行交叉连接,并排除其他记录中的那些记录

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值。作为开发人员,这通常是您做错事情的第一个迹象。在极少数情况下,应该对值进行硬编码;而是将它们作为变量存储在表中,从而无需更改代码即可灵活地进行更改。

答案 1 :(得分:1)

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中几乎没有用。

答案 2 :(得分:1)

您可以使用以下方式将映射硬编码到视图中:

<?xml version="1.0" encoding="UTF-8"?>
<table>
  <Row>
    <Cell>test name1</Cell>
    <Cell>11111 000 000</Cell>
    <Cell>453</Cell>
    <Cell>452</Cell>
  </Row>
  <Row>
    <Cell>test name2</Cell>
    <Cell>22222 000 000</Cell>
    <Cell>502</Cell>
    <Cell>503</Cell>
  </Row>
</table>

我会高度建议您不要。如果并且当您想添加,编辑或删除映射时,通过在表中插入/更新/删除行比在视图中进行更改要容易得多。

相反,最好创建一个junction table (Associative entity)

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);

Examples on DB<>Fiddle

答案 3 :(得分:1)

您似乎想要:

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

我不确定您是否正在寻找一种更简洁的编写方式。