【问题标题】:SQL Join instead of UNIONSQL 联接而不是 UNION
【发布时间】:2021-01-27 22:07:58
【问题描述】:

我有以下表格:

Table T1
--------------------------
ZID   | NAME 
------------------------
1     | Test 

Table C1 
--------------------------
ZID   | VALUE1 
------------------------
1     | A 
1     | B

Table S1 
--------------------------
ZID   | VALUE2 
------------------------
1     | C 
1     | D

我想要一个选择查询来获取以下值

----------------------------------
ZID   | NAME  | VALUE1  | VALUE2  
----------------------------------
1     | Test  |    A    |   null 
1     | Test  |    B    |   null 
1     | Test  |   null  |    C 
1     | Test  |   null  |    D

我可以通过使用UNION 来实现上述目的,方法是在每个选择中伪造一列,如下所示。

SELECT
    ZID,
    NAME,
    VALUE1,
    NULL AS VALUE2
FROM
    T1
    LEFT JOIN C1 ON (
        T1.ZID = C1.ZID
    )
UNION ALL 
(
SELECT
    ZID,
    NAME,
    NULL AS VALUE1,
    VALUE2
FROM
    T1
    LEFT JOIN S1 ON (
        T1.ZID = S1.ZID
    )
);

是否可以使用 JOINS 在单次选择中检索上述数据?我曾尝试使用左连接,但结果中的数据是笛卡尔积。

【问题讨论】:

  • 戈登的回答巧妙地满足了您的要求。但我希望您的两个LEFT JOIN 中的UNION ALL(使用表限定zid 修复语法)在许多情况下会更快。看不出排除UNION的理由?另外:Postgres 在查询中不需要任何括号。
  • 谢谢欧文。是的,括号是为了我的利益。它有助于我更好地理解。

标签: sql postgresql h2


【解决方案1】:

可以使用:

select t1.*, c1.value1, s1.value2
from c1 full join
     s1
     on false join
     t1
     on t1.id in (c1.id, s1.id)

false 上的 full join 很像 union all

【讨论】:

  • Sql fiddle 证明这一点(也可以帮助其他人验证他们的答案)。
【解决方案2】:

联合会给你更多的行。加入会给你更多的列。如果要连接它们以获得包含所有列的一组行,则需要指定哪些行放在一起。例如,如果您不指定哪个 C1 行与哪个 S1 行匹配,它会将每个行与所有行匹配,并给出您不想要的产品。

在 on 子句中定义关系,它会做你想做的事。

【讨论】:

  • 能否请您发布一个关于 on 子句的示例?
  • 由于您只有 1 个 ZID 值,因此无法使用所提供的数据来指定 S1 中的哪一行与 C1 中的哪一行相关。更能代表您的用例的数据可能会有所帮助。
  • 如果 ZID 是相关项,则选择 * from T1 left join C1 on T1.ZID=C1.ZID left join S1 on T1.ZID=S1.ZID;
  • 如果它总是匹配每个表上的行,请从 T1,C1,S1 中选择 *,其中 T1.ZID=C1.ZID 和 T1.ZID=S1.ZID。
  • ZID 是 C1 和 S1 中的外键,但是对它们进行 JOIN 并没有帮助。我仍然得到一个笛卡尔积
【解决方案3】:

查询将类似于:

SELECT ZID, NAME, VALUE1, VALUE2
FROM T1, C1, S1;

【讨论】:

  • 应该是LEFT OUTER JOIN S1
  • 由于C1和S1之间没有关系,所以还是笛卡尔积。
【解决方案4】:

您需要UNION 来添加行。您可以将连接放在UNION 的外部以避免必须执行两次:

SELECT
    ZID,
    NAME,
    VALUE1,
    NULL AS VALUE2

FROM
    T1
LEFT JOIN (
    SELECT ZID, VALUE1, NULL AS VALUE2
        FROM C1
    UNION ALL
    SELECT ZID, NULL AS VALUE1, VALUE2
        FROM S1 
) Merged ON T1.ZID = Merged.ZID

【讨论】:

    猜你喜欢
    • 2016-04-18
    • 1970-01-01
    • 2018-06-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-29
    • 2023-03-11
    • 2016-03-10
    相关资源
    最近更新 更多