如何在语句中重写嵌套子查询

时间:2014-08-13 20:08:11

标签: sql sql-server tsql

我在in内有一个嵌套子查询的查询。有没有人有更好/更短的方式来重写这个查询:

select *
  from Table1 t1
 where t1.column1 in (select t21.column1
                        from Table2 t21
                       where t21.column2 in (select t31.column2
                                               from Table3 t31
                                              where t31.column3 = 'Value1'))
   and t1.column1 in (select t22.column1
                        from Table2 t22
                       where t22.column2 in (select t32.column2
                                               from Table3 t32
                                              where t32.column3 = 'Value2'))

请注意,最内层子查询在where条件中具有不同的值。


修改 我得到了很好的回复,但我还没有得到满足我的需求或避风港的简化形式,无法从答案中推断出来。我想我对自己的要求不够清楚。我可以在两个内部子查询中加入一个并得到我需要的东西。所以,现在的问题是,是否可以以可读的方式进一步压缩以下查询:

select *
  from Table1 t1
 where t1.column1 in (select t21.column1
                        from Table2 t21
                               join
                             Table3 t31
                               on t21.column2 = t31.column2
                       where t31.column3 = 'Value1'))
   and t1.column1 in (select t21.column1
                        from Table2 t21
                               join
                             Table3 t31
                               on t21.column2 = t31.column2
                       where t31.column3 = 'Value2'))

5 个答案:

答案 0 :(得分:4)

我相信你应该可以使用INNER JOIN来做这件事,虽然这是未经测试的,所以我可以完全离开。

SELECT t1.*
FROM Table1 t1
    INNER JOIN Table2 t2 ON t1.column1 = t2.column1
    INNER JOIN Table3 t3 ON t2.column2 = t3.column2
WHERE t3.column3 IN ('Value1', 'Value2')

修改

重新审视OP comment,我想你可能真的需要更多这样的东西:

SELECT t1.*
FROM Table1 t1
    INNER JOIN Table2 t2 ON t1.column1 = t2.column1
WHERE t2.column2 IN (SELECT t3.column2
                     FROM Table3 t3
                     WHERE t3.column3 = 'Value1'
      AND t2.column2 IN (SELECT t3.column2
                         FROM Table3 t3
                         WHERE t3.column3 = 'Value2'

它并不是很好,但我认为你需要做的就是处理AND案件。

编辑2:

或者更好的是,这可能是完全无稽之谈,但这些内容有以下几点:

SELECT DISTINCT t1.*
FROM Table1 t1
    INNER JOIN Table2 t2 ON t1.column1 = t2.column1
    INNER JOIN Table3 t3a ON t2.column2 = t3a.column2
    INNER JOIN Table3 t3b ON t2.column2 = t3b.column2
WHERE (t3a.column3 = 'Value1' AND t3b.column3 = 'Value2') OR
      (t3a.column3 = 'Value2' AND t3b.column3 = 'Value1')

我不完全确定你是否需要最后一行。

答案 1 :(得分:1)

以代数方式扩展:

If {X} =>
    select *
    from Table1
    where column1 in ({A})
      and column1 in ({B})

Then {X} =>
    select *
    from Table1
    where column1 in ({A} INTERSECT {B})
-----------------------------------------
If {A} =>
    select column1
    from Table2
    where column2 in ({C})

And {B} =>
    select column1
    from Table2
    where column2 in ({D})

Then {A} INTERSECT {B} =>
    select column1
    from Table2
    where column2 in ({C} INTERSECT {D})
-----------------------------------------
If {C} =>
    select column2
    from Table3
    where column3 = 'Value1'

And {D} =>
    select column2
    from Table3
    where column3 = 'Value2'

Then {C} INTERSECT {D} =>
    select column2
    from Table3
    where column3 IN ('Value1','Value2')
    group by column2
    having count(distinct column3) = 2
-----------------------------------------

代替:

select *
from Table1 t1
where t1.column1 in (select t2.column1
                     from Table2 t2
                     where t2.column2 in (select t3.column2
                                          from Table3 t3
                                          where t3.column3 IN ('Value1','Value2')
                                          group by t3.column2
                                          having count(distinct t3.column3) = 2)

<强>压实:

select *
from Table1 t1
where exists (select 1
              from Table2 t2
              where t2.column1 = t1.column1
                and exists (select 1
                            from Table3 t3
                            where t3.column2 = t2.column2
                              and t3.column3 IN ('Value1','Value2')
                            group by t3.column2
                            having count(distinct t3.column3) = 2)

您可以继续重写,将exists更改为inner joins,但这不会更改查询计划。

答案 2 :(得分:0)

试试这个:

SELECT t1.* FROM Table1 t1
LEFT JOIN Table2 t2 ON t1.column1 = t2.column1
LEFT JOIN Table3 t3 ON t21.column2 = t31.column2
WHERE t31.column3 IN ('Value1', 'Value2')

测试,您可能希望将其更改为INNER JOIN

答案 3 :(得分:0)

这些可以转换为联接。也许是这样的:

select     Table1.Column1, Table1.Column2, Table1.Column3--and so forth
from       Table1
inner join Table2
    on     Table2.Column1 = Table1.Column1
inner join Table3
    on     Table3.Column2 = Table2.Column2
    and    Table3.Column3 in ('Value1','Value2')
group by   Table1.Column1, Table1.Column2, Table1.Column3
having     COUNT(distinct Table3.Column3)>=2

更新: 我看到其他的例子即将结束,但只是使用“... Column3 in ...”将不会完全削减它。在原始问题中,Table1.Column1必须链接到'Value1'和'Value2',因为这就是AND的工作方式。

答案 4 :(得分:0)

是等同的吗?

SELECT 
    *
FROM 
    Table1 t1 INNER JOIN
    (SELECT 
            t2.column1
        FROM 
            Table2 t2 INNER  JOIN
            Table3 t3  ON 
            t2.column2 = t3.column2 AND 
            t3.column3 = 'Value1'
    ) v1 ON
    t1.column1 = v1.column1 INNER JOIN
    (SELECT 
            t2.column1
        FROM 
            Table2 t2 INNER JOIN
            Table3 t3 ON
            t2.column2 = t3.column2 AND 
            t3.column3 = 'Value2'
    ) v2 ON
    t1.column1 = v2.column1

SELECT 
    *
FROM 
    Table1 t1 INNER JOIN
    (SELECT DISTINCT
            t2.column1
    FROM 
            Table2 t2 INNER  JOIN
            Table3 t3  ON 
            t2.column2 = t3.column2 AND 
            t3.column3 = 'Value1' INNER  JOIN
            Table3 t4  ON 
            t2.column2 = t4.column2 AND 
            t4.column3 = 'Value2'
    ) v ON
    t1.column1 = v.column1 

不确定您是否需要distinct

样本数据有助于我们测试