【问题标题】:Inner join 2 tables but return all if 1 table emptySQL - 内连接 2 个表,但如果 1 个表为空,则返回所有表
【发布时间】:2013-02-22 07:04:12
【问题描述】:

我有 2 个表 A 和 B,我想对它们进行连接。

表 A 中将始终有记录。

当表 B 中有行时,我希望查询转换表 A 和表 B 匹配的所有行。 (即表现得像内连接)

但是,如果表 B 为空,我想返回表 A 中的所有内容。

这可以在 1 个查询中完成吗?

谢谢。

【问题讨论】:

  • 曾经设法解决这个问题?
  • @viv_acious:你能找到解决办法吗?

标签: sql join left-join inner-join


【解决方案1】:

是的,对于这样的结果,请使用LEFT JOIN

基本上INNER JOIN 所做的是它只返回在另一个表上至少有一个匹配项的行。另一方面,LEFT JOIN 返回左侧表上的所有记录,无论它在另一张表上是否不匹配。

如需进一步了解联接,请访问以下链接:

【讨论】:

  • 但是当表 B 有记录时,我不希望查询返回所有内容(甚至不匹配)...我希望它像内部连接一样执行。只有当表 B 为空时,我才想返回表 A 中的所有内容。这有意义吗?
  • @viv_acious:你能找到解决办法吗?
【解决方案2】:

我遇到了同样的问题,但由于从未得到解答,因此我在其他地方发布了针对此问题的解决方案,以防将来对某人有所帮助。 请参阅source

select *
from TableA as a
left join TableB as b
    on b.A_Id = a.A_Id
where
    b.A_Id is not null or
    not exists (select top 1 A_Id from TableB)

【讨论】:

  • 哎呀,这不是对初始结果中的每一行都进行表扫描吗?
【解决方案3】:

试试这个

SELECT t1.* FROM table1 AS t1 INNER JOIN table2 AS t2 ON t1.something = t2.someotherthing UNION SELECT * FROM table1 WHERE something = somethingelse;

【讨论】:

  • 您使 LEFT JOIN 复杂化,我不确定您的查询是否适用于所提出的问题
【解决方案4】:

这是解决方案:

CREATE TABLE MyData(Id INT, Something VARCHAR(10), OwnerId INT);
CREATE TABLE OwnerFilter(OwnerId INT);

SELECT * 
FROM 
(SELECT NULL AS Gr) AS Dummy
LEFT JOIN OwnerFilter F ON (1 = 1)
JOIN MyData D ON (F.OwnerId IS NULL OR D.OwnerId = F.OwnerId);

sqlfiddle 链接:http://sqlfiddle.com/#!6/0f9d9/7

【讨论】:

    【解决方案5】:

    这是另一个,但如果它是空的,你需要在表 B 中添加一个“null”行

    -- In case B is empty
    Insert into TableB (col1,col2) values (null,null)
    
    select * 
    from TableA as a inner join TableB as b
    on 
        b.A_Id = a.A_Id
        or b.A_Id is null
    

    【讨论】:

      【解决方案6】:

      我会使用 if-else 块来解决它,如下所示:

      if (select count(*) from tableB) > 0
      begin
         Select * from TableA a Inner Join TableB b on a.ID = b.A_ID
      end
      else
      begin
         Select * from TableA
      end
      

      【讨论】:

      • 这应该是公认的答案,没有其他简单的方法可以解决这个问题。
      【解决方案7】:

      我做了以下事情:

      DECLARE @TableB TABLE (id INT)
      -- INSERT INTO @TableB
      -- VALUES (some ids to filter by)
      
      SELECT TOP 10 *
      FROM [TableA]          A
           LEFT JOIN @TableB B
                     ON A.ID = B.id
      WHERE B.id IS NOT NULL
         OR iif(exists(SELECT *
                       FROM TableB), 1, 0) = 0
      

      现在: 如果 TableB 为空(保留注释行),您将获得前 10 名。 如果 TableB 中有一些 id,您将只能通过这些 id 加入。

      我不知道这有多有效。欢迎评论。

      【讨论】:

        【解决方案8】:

        也许使用 CTE

        ;WITH ctetable(
         Select * from TableA
        )
            
        IF(EXISTS(SELECT 1 FROM TableB))
        BEGIN
         Select * from ctetable 
          Inner join TableB
        END
        ELSE 
        BEGIN
         Select * from ctetable 
        END
        

        或动态 SQL

        DECLARE @Query NVARCHAR(max);
        SET @QUERY = 'Select * FROM TableA';
        IF(EXISTS(SELECT 1 FROM TableB))
        BEGIN
         SET @QUERY = CONCAT(@QUERY,' INNER JOIN TableB');
        END
        EXEC sp_executesql @Query
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-03-12
          • 1970-01-01
          • 2018-03-05
          • 2011-08-17
          • 2018-02-28
          • 2013-09-03
          • 2022-12-22
          相关资源
          最近更新 更多