【问题标题】:LEFT JOIN but with additional rows from parent tableLEFT JOIN,但有父表中的其他行
【发布时间】:2019-07-08 02:15:00
【问题描述】:

不知道该怎么称呼它,--我确定这必须在其他地方问。

考虑以下,例如。

CREATE TABLE abbrv (
    abbrv_id int unsigned primary key not null auto_increment,
    usps_primary varchar(64) not null,
    usps_preferred varchar(16) not null
);

CREATE TABLE abbrv_variation (
    variation_id int unsigned primary key not null auto_increment,
    abbrv_id int unsigned, -- FK
    variation varchar(64) not null
);

INSERT INTO abbrv(usps_primary, usps_preferred) VALUES('North', 'N');
INSERT INTO abbrv(usps_primary, usps_preferred) VALUES('South', 'S');
INSERT INTO abbrv(usps_primary, usps_preferred) VALUES('East', 'E');
INSERT INTO abbrv(usps_primary, usps_preferred) VALUES('West', 'W');

INSERT INTO `abbrv` (usps_primary, usps_preferred) values('ALLEY', 'ALY');
SET @abbrvId = LAST_INSERT_ID();
INSERT INTO `abbrv_variation` (abbrv_id, variation) VALUES(@abbrvId, 'ALLEE');
INSERT INTO `abbrv_variation` (abbrv_id, variation) VALUES(@abbrvId, 'ALLY');

INSERT INTO `abbrv` (usps_primary, usps_preferred) values('ANEX', 'ANX');
SET @abbrvId = LAST_INSERT_ID();
INSERT INTO `abbrv_variation` (abbrv_id, variation) VALUES(@abbrvId, 'ANNEX');
INSERT INTO `abbrv_variation` (abbrv_id, variation) VALUES(@abbrvId, 'ANNX');
INSERT INTO `abbrv_variation` (abbrv_id, variation) VALUES(@abbrvId, 'ANX');

我只是想做的是返回如下内容:

+--------------+----------------+-----------+
| usps_primary | usps_preferred | variation |
+--------------+----------------+-----------+
| North        | N              | North     | <-- 1 row for "usps_primary"
| North        | N              | N         | <-- 1 row for "usps_preferred"
| South        | S              | South     | <-- 1 row for "usps_primary"
| South        | S              | S         | <-- 1 row for "usps_preferred"
| East         | E              | East      | <-- 1 row for "usps_primary"
| East         | E              | E         | <-- 1 row for "usps_preferred"
| West         | W              | West      | <-- 1 row for "usps_primary"
| West         | W              | W         | <-- 1 row for "usps_preferred"
| ALLEY        | ALY            | ALLEY     | <-- 1 row for "usps_primary"
| ALLEY        | ALY            | ALY       | <-- 1 row for "usps_preferred"
| ALLEY        | ALY            | ALLEE     | X-- one row for each 
| ALLEY        | ALY            | ALLY      | X-- variation    
| ANEX         | ANX            | ANEX      | <-- 1 row for "usps_primary"
| ANEX         | ANX            | ANX       | <-- 1 row for "usps_preferred"
| ANEX         | ANX            | ANNEX     | X-- one row for each 
| ANEX         | ANX            | ANNX      | X-- variation    

顺序无关紧要 - 只是它们都在那里。最初,此表仅包含其中每一个的“变体”行,但它变得无法维护,因为它是一个非常大的表,以确保每次添加新变体时都输入所有这些行。

我当然尝试过简单的 LEFT JOIN、CROSS JOIN、OUTER JOIN、左连接和右连接 - 我真的不知道这里的适当做法是什么。

交叉连接似乎大致正确,但我不想要整个系列,每个只有 2 次。

【问题讨论】:

    标签: mysql join cross-join


    【解决方案1】:
    SELECT usps_primary, usps_preferred, usps_primary AS variation FROM abbrv
    UNION
    SELECT usps_primary, usps_preferred, usps_preferred FROM abbrv
    UNION
    SELECT a.usps_primary, a.usps_preferred, v.variation FROM abbrv AS a 
    INNER JOIN abbrv_variation AS v USING (abbrv_id)
    ORDER BY usps_primary
    

    输出:

    +--------------+----------------+-----------+
    | usps_primary | usps_preferred | variation |
    +--------------+----------------+-----------+
    | ALLEY        | ALY            | ALLEY     |
    | ALLEY        | ALY            | ALLEE     |
    | ALLEY        | ALY            | ALLY      |
    | ALLEY        | ALY            | ALY       |
    | ANEX         | ANX            | ANX       |
    | ANEX         | ANX            | ANNX      |
    | ANEX         | ANX            | ANEX      |
    | ANEX         | ANX            | ANNEX     |
    | East         | E              | E         |
    | East         | E              | East      |
    | North        | N              | North     |
    | North        | N              | N         |
    | South        | S              | South     |
    | South        | S              | S         |
    | West         | W              | W         |
    | West         | W              | West      |
    +--------------+----------------+-----------+
    

    【讨论】:

      【解决方案2】:

      你可以使用LATERAL:

      SELECT usps_primary, usps_preferred, s.variation
      FROM abbrv a
      ,LATERAL(SELECT a.usps_primary AS variation
               UNION SELECT a.usps_preferred 
               UNION SELECT av.variation FROM abbrv_variation av WHERE a.abbrv_id = av.abbrv_id) s
      

      db<>fiddle demo

      输出:

      +---------------+-----------------+-----------+
      | usps_primary  | usps_preferred  | variation |
      +---------------+-----------------+-----------+
      | North         | N               | North     |
      | North         | N               | N         |
      | South         | S               | South     |
      | South         | S               | S         |
      | East          | E               | East      |
      | East          | E               | E         |
      | West          | W               | West      |
      | West          | W               | W         |
      | ALLEY         | ALY             | ALLEY     |
      | ALLEY         | ALY             | ALY       |
      | ALLEY         | ALY             | ALLEE     |
      | ALLEY         | ALY             | ALLY      |
      | ANEX          | ANX             | ANEX      |
      | ANEX          | ANX             | ANX       |
      | ANEX          | ANX             | ANNEX     |
      | ANEX          | ANX             | ANNX      |
      +---------------+-----------------+-----------+
      

      【讨论】:

      • @mangusta 第一次尝试没有意义。我留下了最终答案:D
      猜你喜欢
      • 2011-07-01
      • 1970-01-01
      • 2013-02-20
      • 1970-01-01
      • 2013-07-02
      • 1970-01-01
      • 2022-11-29
      • 2021-09-11
      • 2015-04-15
      相关资源
      最近更新 更多