如何同时拥有IN和NOT IN

时间:2015-12-17 17:01:14

标签: sql sql-server

有人可以帮我弄清楚最好的方法是什么?

我有车辆清单。我需要执行一个查询,该查询将返回具有某种类型的汽车且同时没有其他类型的人。

以下是我的例子:

ID          Name       CarType
----------- ---------- ----------
1           John       MINI VAN
1           John       SUV
2           Mary       SUV
2           Mary       SEDAN
3           Paul       SPORT
3           Paul       TRUCK
4           Joe        SUV
4           Joe        MINI VAN

例如,我想只显示有SUV且没有MINI VAN的人。如果我们尝试子句CarType IN('SUV')而不是IN('MINI VAN'),这将不起作用,因为第二个语句只是被忽略。

为了返回有类型但同时没有其他类型的人,我尝试了以下内容:

  • 使用IN子句创建一个临时表,比方说@Contains
  • 使用NOT IN子句创建一个临时表,假设是@DoesNotContain
  • 与@Contains联系,这将执行IN子句
  • 在where子句中,查找不在@DoesNotContain表中的ID。

我正在使用的查询是:

--This is the IN Clause
declare @Contains table(
 ID int not null
)
--This is the NOT IN Clause
declare @DoesNotContains table(
 ID int not null
)

--Select IN
insert into @Contains
SELECT ID from @temp where CarType = 'SUV'

--Select NOT IN
insert into @DoesNotContains
SELECT ID from @temp where CarType = 'MINI VAN'

SELECT 
    a.ID, Name 
FROM
    @temp a 
    INNER JOIN @Contains b on b.ID = a.ID
WHERE 
    a.ID NOT IN (SELECT ID FROM @DoesNotContains)
Group by 
    a.ID, Name

这将归还Mary,因为她有一辆SUV,但没有MINI VAN。

以下是我的问题:

  • 在没有临时表的情况下,是否可以在查询中执行此IN和NOT IN? SQL中有新的东西吗? (抱歉,我上次使用SQL时是SQL 2005)
  • 我们应该使用临时表吗?
  • 如果这是要走的路,我应该使用IN而不是IN而不是JOIN吗?
  • 如何用JOIN替换NOT IN子句?

谢谢你们!

修改

我刚刚测试了这些解决方案,但不幸的是我没有说明我需要组合使用这些类型的解决方案。我的坏:(

例如,如果我希望所有用户都拥有SUV和MINI VAN而不是TRUCK而不是SEDAN。在这种情况下,只返回John。

4 个答案:

答案 0 :(得分:6)

这通常使用NOT EXISTS

在标准SQL中使用单个查询来完成
SELECT *
FROM mytable AS t1
WHERE CarType = 'SUV' AND 
      NOT EXISTS (SELECT *
                  FROM mytable AS t2 
                  WHERE t1.Name = t2.Name AND t2.CarType = 'MINI VAN')

上述查询会选择所有CarType = 'SUV'但没有CarType = 'MINI VAN'的人。

答案 1 :(得分:5)

这是单程

SELECT Id, Name
FROM Cars 
WHERE CarType = 'SUV'
EXCEPT
SELECT Id, Name
FROM Cars 
WHERE CarType = 'MINI VAN'

或另一个

SELECT Id, Name
FROM Cars 
WHERE CarType IN ('SUV', 'MINI VAN')
GROUP BY Id, Name
HAVING MIN(CarType) = 'SUV'

或更通用的版本,以解决评论中的不同要求。

SELECT Id,
       NAME
FROM   Cars
WHERE  CarType IN ( 'SUV', 'MINI VAN', 'TRUCK')
GROUP  BY Id,
          NAME
HAVING COUNT(DISTINCT CASE
                        WHEN CarType IN ( 'SUV', 'MINI VAN' ) THEN CarType
                      END) = 2
       AND COUNT(DISTINCT CASE
                            WHEN CarType IN ( 'TRUCK' ) THEN CarType
                          END) = 0 

答案 2 :(得分:0)

使用LEFT JOIN

SELECT  a.ID,
        Name
FROM    @temp a
    INNER JOIN @Contains b ON b.ID = a.ID
    LEFT OUTER JOIN @DoesNotContains c ON c.ID = a.ID
WHERE   c.ID IS NULL

INNER JOIN将返回b.IDa.ID匹配的记录。

LEFT OUTER JOIN会返回所有记录,其中NULL没有匹配 - 添加WHERE c.ID IS NULL会返回不匹配的a记录< / em>到c

答案 3 :(得分:0)

关键字def myMap (f: Int=>Int) ( L:List[Int]) : List[Int] = { var xx = L if(L.isEmpty) Nil val (head::tail) = xx f(head) :: myMap (f) (tail) } 是您的朋友。这是一般的想法

except

你可以弄清楚细节。