在不使用"左连接"的情况下模拟左连接

Fra*_*sco 13 sql

我需要模拟左连接效果而不使用"左连接"键.

我有两个表,A和B,都有idname列.我想在两个表中选择所有dbid,其中A中的名称等于B中的名称.

我使用它来进行同步,所以在开始时B是空的(所以我将有一对来自A的id,其值为一,而来自B的id为null).后来我将有价值的夫妻 - 价值和价值 - 无效.

通常它会是:

SELECT A.id, B.id
FROM A left join B
ON A.name = B.name
Run Code Online (Sandbox Code Playgroud)

问题是我不能使用left join并想知道是否/如何做同样的事情.

Mar*_*ith 17

只需反转表并使用右连接.

SELECT A.id,
       B.id
FROM   B
       RIGHT JOIN A
         ON A.name = B.name  
Run Code Online (Sandbox Code Playgroud)

  • 如果他不能使用左连接,我怀疑他可以使用正确的连接. (7认同)

Die*_*ego 15

您可以使用此方法,但必须确保内部选择仅返回一行.

SELECT A.id, 
(select B.id from B where  A.name = B.name) as B_ID
FROM A 
Run Code Online (Sandbox Code Playgroud)

  • 这不等同于`LEFT JOIN`.或者,准确地说,它只相当于`B(name)`具有'UNIQUE`约束. (2认同)

one*_*hen 13

我不熟悉java/jpa.使用纯SQL,这是一种方法:

SELECT A.id AS A_id, B.id AS B_id
  FROM A INNER JOIN B
          ON A.name = B.name
UNION
SELECT id AS A_id, NULL AS B_id 
  FROM A 
 WHERE name NOT IN ( SELECT name FROM B );
Run Code Online (Sandbox Code Playgroud)


Guf*_*ffa 6

例如,在SQL Server中,您可以使用*=运算符进行左连接:

select A.id, B.id
from A, B
where A.name *= B.name
Run Code Online (Sandbox Code Playgroud)

如果存在这样的运算符,则其他数据库的语法可能略有不同.

这是在join引入关键字之前使用的旧语法.当然,join如果可能,您应该使用关键字.旧语法甚至可能不适用于较新版本的数据库.

  • 我仍然在你的查询中看到`LEFT JOIN`.我错过了什么吗? (2认同)
  • * *仅适用于Microsoft SQL Server。Oracle使用`(+)`。所有其他人根本没有这样的运算符。 (2认同)

Eri*_*ikE 5

我只能想到两种目前还没有给出的方法。我的最后三个想法已经给出(嘘),但我把它们放在这里供后代使用。我确实想到了他们,没有作弊。:-p

  1. 计算 B 是否有匹配,然后为 B 集提供一个额外的 UNIONed 行,以便在没有匹配时提供 NULL。

     SELECT A.Id, A.Something, B.Id, B.Whatever, B.SomethingElse
     FROM
        (
           SELECT
              A.*,
              CASE
                 WHEN EXISTS (SELECT * FROM B WHERE A.Id = B.Id) THEN 1
                 ELSE 0
              END Which
           FROM A
        ) A
        INNER JOIN (
           SELECT 1 Which, B.* FROM B
           UNION ALL SELECT 0, B* FROM B WHERE 1 = 0
        ) B ON A.Which = B.Which
           AND (
              A.Which = 0
              OR (
                 A.Which = 1
                 AND A.Id = b.Id
              )
           )
    
    Run Code Online (Sandbox Code Playgroud)
  2. 对同一查询的稍微不同的处理:

     SELECT A.Id, B.Id
     FROM
        (
           SELECT
              A.*,
              CASE
                 WHEN EXISTS (SELECT * FROM B WHERE A.Id = B.Id) THEN A.Id
                 ELSE -1 // a value that does not exist in B
              END PseudoId
           FROM A
        ) A
        INNER JOIN (
           SELECT B.Id PseudoId, B.Id FROM B
           UNION ALL SELECT -1, NULL
        ) B ON A.Which = B.Which
           AND A.PseudoId = B.PseudoId
    
    Run Code Online (Sandbox Code Playgroud)
  3. 仅专门针对 SQL Server。我知道,这确实是一个左连接,但它并没有LEFT在那里说!

    SELECT A.Id, B.Id
    FROM
       A
       OUTER APPLY (
          SELECT *
          FROM B
          WHERE A.Id = B.Id
       ) B
    
    Run Code Online (Sandbox Code Playgroud)
  4. 获取内连接,然后 UNION 外连接:

    SELECT A.Id, B.Id
    FROM
       A
       INNER JOIN B ON A.name = B.name
    UNION ALL 
    SELECT A.Id, NULL
    FROM A
    WHERE NOT EXISTS (
       SELECT *
       FROM B
       WHERE A.Id = B.Id
    )
    
    Run Code Online (Sandbox Code Playgroud)
  5. 使用右连接。这不是左连接!

    SELECT A.Id, B.Id
    FROM
       B
       RIGHT JOIN A ON B.name = A.name
    
    Run Code Online (Sandbox Code Playgroud)
  6. 只需在子查询表达式中选择 B 值(我们希望每个 A 仅有一个 B)。B 中的多个列可以是它们自己的表达式(YUCKO!):

    SELECT A.Id, (SELECT TOP 1 B.Id FROM B WHERE A.Id = B.Id) Bid
    FROM A
    
    Run Code Online (Sandbox Code Playgroud)

使用 Oracle 的任何人都可能需要FROM DUAL在任何没有 FROM 的 SELECT 中使用一些子句。