【问题标题】:How do I create a special case Intersect clause in SQL?如何在 SQL 中创建特殊情况的 Intersect 子句?
【发布时间】:2019-08-14 07:11:41
【问题描述】:

我需要一组值,只有当它们在两个不同的选择语句中可用时,所以我使用了“相交”

(select statement 1) intersect (select statement 2)

但是当另一个 select 语句返回没有值时,我想要一个 select 语句中的所有值。

示例 1:

Statement 1 returns(1,2,3,4,5) and Statement 2 returns(2,5,8,9);
Expected result 1: (2,5)

示例 2:

Statement 1 returns(NULL) and Statement 2 returns(2,5,8,9);
Expected result 1: (2,5,8,9)

---编辑:为清楚起见添加第三个示例---

示例 3:

Statement 1 returns(2,5,8,9) and Statement 2 returns(NULL);
Expected result 1: (2,5,8,9)

---编辑 2--- 我在

中使用此选择

【问题讨论】:

  • 您使用的是哪个数据库?
  • @Magnus 我正在使用 sql-server。

标签: sql sql-server union intersect


【解决方案1】:

对于第一种情况,您可以使用 INNER JOIN

select  col 
from  (
  select 1 col union all 
  select 2 union all 
  select 3 union all 
  select 4 union all 
  select 5
) t1  
inner join  (
  select 2 col union all 
  select 5 union all 
  select 8  union all 
  select 9
) t2  ON t1.col = t2.col

第二个你可以尝试使用右连接检查空值

select  col 
from  (
  select 1 col union all 
  select 2 union all 
  select 3 union all 
  select 4 union all 
  select 5
) t1  
right join  (
  select 2 col union all 
  select 5 union all 
  select 8  union all 
  select 9
) t2  ON t1.col = t2.col
where t1.col is null 

【讨论】:

  • 如果用户想要不匹配的值,你不应该使用外连接吗?
【解决方案2】:

有几种方法可以做你想做的事,但你需要根据你期望空语句的位置正确放置表格:

DECLARE @t1 TABLE
(
ID INTEGER
);

DECLARE @t2 TABLE
(
ID INTEGER
);

DECLARE @t3 TABLE
(
ID INTEGER
);

INSERT INTO @t1 VALUES (1),(2),(3),(4),(5);

INSERT INTO @t2 VALUES (2),(5),(8),(9);

SELECT *
FROM @t1 t1
INNER JOIN @t2 t2 ON t1.ID = t2.ID;

--Example 2, you can use either a FULL JOIN
SELECT *
FROM @t1 t1
FULL JOIN @t3 t3 ON t1.ID = t3.ID;

--Example 2, or you can use a LEFT JOIN. But you need to put the table that is likely to have data as the 
--main table in a LEFT JOIN
SELECT *
FROM @t1 t1
LEFT JOIN @t3 t3 ON t1.ID = t3.ID;

【讨论】:

    【解决方案3】:

    伪代码

    bool flag := exists (select 1 from Statement_2);
    select *
    from Statement_1 t1
    where exists (select 1 from Statement_2 t2 where t1.key = t2.key) or not flag;
    

    Sql server 版本,将key替换成真实key比较。

    declare @flag bit = case when exists (select 1 from Statement_2)
                       then 1 else 0 end;
    select *
    from Statement_1 t1
    where exists (select 1 from Statement_2 t2 where t1.key = t2.key) or @flag = 0;
    

    【讨论】:

      【解决方案4】:

      这将是另一种方式:

      --Setup
      create table #table1(id int);
      insert into #table1(id) values (1), (2), (3), (4), (5);
      
      create table #table2(id int);
      insert into #table2(id) values (2), (5), (8), (9);
      
      --Query
      select 
          ISNULL(a.id, b.id) id
      from
          #table1 a full outer join #table2 b on a.id = b.id
      where 
          not exists(select null from #table1) or 
          not exists(select null from #table2) or
          (a.id is not null and b.id is not null)
      

      【讨论】:

        【解决方案5】:

        像这样使用UNION ALL

        (
          select statement 1
          union all
          select statement 2  
          where not exists (
            select statement 1
          )
        )
        intersect
        (
          select statement 2
          union all
          select statement 1  
          where not exists (
            select statement 2
          )
        ) 
        

        如果select statement X 已经包含WHERE 子句,请在末尾使用AND 来应用条件not exists (...)
        请参阅demo
        对于这些表:

        create table table1(id int);
        insert into table1(id) values (1), (2), (3), (4), (5);
        
        create table table2(id int);
        insert into table2(id) values (2), (5), (8), (9);
        

        案例:

        (
          select * from table1
          union all
          select * from table2  
          where not exists (
            select * from table1
          )
        )
        intersect
        (
          select * from table2
          union all
          select * from table1  
          where not exists (
            select * from table2
          )
        )
        

        结果是:

        > | id |
        > | -: |
        > |  2 |
        > |  5 |
        

        案例:

        (
          select * from table1 where id > 9
          union all
          select * from table2  
          where not exists (
            select * from table1 where id > 9
          )
        )
        intersect
        (
          select * from table2
          union all
          select * from table1 where id > 9 
          and not exists (
            select * from table2
          )
        )
        

        结果是:

        > | id |
        > | -: |
        > |  2 |
        > |  5 |
        > |  8 |
        > |  9 |
        

        对于案例:

        (
          select * from table1
          union all
          select * from table2 where id > 9 
          and not exists (
            select * from table1
          )
        )
        intersect
        (
          select * from table2 where id > 9
          union all
          select * from table1
          where not exists (
            select * from table2 where id > 9
          )
        )
        

        结果是:

        > | id |
        > | -: |
        > |  1 |
        > |  2 |
        > |  3 |
        > |  4 |
        > |  5 |
        

        【讨论】:

          【解决方案6】:

          您可能想试试这个,看看它是否更快:

          with
              s1 as (select count(*) over () c1, <query1> ...),
              s2 as (select count(*) over () c2, <query2> ...),
          )
          select coalesce(t1.id, t2.id) as id
          from table1 t1 full outer join table2 t2
              on t2.id = t1.id and c1 > 0 and c2 > 0
          );
          

          【讨论】:

            【解决方案7】:

            我想我会这样做:

            select t1.id
            from t1
            where exists (select 1 from t2 where t2.id = t1.id)
            union all
            select t1.id
            from t1
            where not exists (select 1 from t2)
            union all
            select t2.id
            from t2
            where not exists (select 1 from t1);
            

            如果您的语句是,那么优化器应该能够产生高效的执行计划。如果语句是复杂的表达式,那么您可能需要不同的方法。如果是这样,了解该声明的内容会很有帮助。可能有一种最佳方式来表达更多信息的逻辑。

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2015-10-21
              • 2016-10-23
              • 1970-01-01
              • 2016-11-05
              相关资源
              最近更新 更多