如何在不使用NOT IN

时间:2017-09-06 13:13:59

标签: sql oracle

我有下面的数据,其中两行有多个数据,其中一些是常见的。所以我想获取两行中不常见的数据。

实施例

Table Demo :
|--T1---------T2----|   
| 100003 | 110000   |
| 100003 | 120000   |
| 100003 | 130000   | 
| 100003 | 140000   |
| 100003 | 150000   |
| 100004 | 110000   |
| 100004 | 120000   |
| 100004 | 160000   |
| 100004 | 170000   |
| 100004 | 180000   |
|-------------------|

Result Set :
|--T1---------T2----|       
| 100003 | 130000   | 
| 100003 | 140000   |
| 100003 | 150000   |
| 100004 | 160000   |
| 100004 | 170000   |
| 100004 | 180000   |
|-------------------|

结果应从两行中删除公共值,即110000,120000。

我使用NOT IN完成了它。但我希望它不使用NOT IN。

以下是我的查询。

 Select distinct T2 
 from Demo 
 where T1 IN ('100003','100004') 
   AND T2 NOT IN (select distinct X.T2 
                  from Demo X
                    inner join Demo Y 
                             ON X.T2 = Y.T2 
                            AND X.T1='100003' 
                            AND Y.T2 ='100004');

注意:我们可以使用相交但它会达到性能所以我买不起它。

6 个答案:

答案 0 :(得分:2)

您可以尝试:

select max(t1), t2 
from table
group by t2
having count(*) = 1;

在这种情况下,我使用max(t1)来显示它,但值在任何情况下都是唯一的(count(*) = 1)。

答案 1 :(得分:2)

您可以使用COUNT分析函数:

SELECT T1,
       T2
FROM   (
  SELECT T1,
         T2,
         COUNT(1) OVER ( PARTITION BY T2 ) AS num
  FROM   demo
)
WHERE  num = 1

答案 2 :(得分:1)

您可以在重复删除后通过自我加入来完成此操作。

WITH demo (t1,t2) AS 
(SELECT 100003 , 110000   UNION ALL
SELECT 100003 , 120000   UNION ALL
SELECT 100003 , 130000   UNION ALL
SELECT 100003 , 140000   UNION ALL
SELECT 100003 , 150000   UNION ALL
SELECT 100004 , 110000   UNION ALL
SELECT 100004 , 120000   UNION ALL
SELECT 100004 , 160000   UNION ALL
SELECT 100004 , 170000   UNION ALL
SELECT 100004 , 180000   )
SELECT a.t1,a.t2
FROM demo a
INNER JOIN (SELECT t2, COUNT(*) cnt FROM demo GROUP BY t2 HAVING COUNT(*) = 1) b
ON a.t2 = b.t2;

T1     |T2    
100004 |160000
100003 |140000
100003 |150000
100004 |180000
100003 |130000
100004 |170000

答案 3 :(得分:0)

首先找到重复的t2值,并从结果中避免它们。

SELECT * FROM Demo WHERE T2 NOT IN 
(SELECT T2 FROM Demo GROUP BY  T2 HAVING COUNT(1) > 1)

答案 4 :(得分:0)

子查询中的distinct没用,但我认为Oracle无论如何都会忽略它。

然而,不需要子查询内的连接,并且会减慢评估中的NOT:

Select distinct T2 
from Demo x1
where T1 IN ('100003','100004') 
  AND T2 NOT IN (select X2.T2 
                 from Demo X2
                 where X1.T1 = X2.t1);

另一种选择是改为使用NOT EXISTS:

Select distinct T2 
from Demo x1
where T1 IN ('100003','100004') 
  AND not exists (select *
                  from Demo X2
                  where X1.T1 = X2.t1);

答案 5 :(得分:0)

您可以使用 <?php include'connection.php'; $pno=$_GET['pno']; $sql="SELECT * FROM user WHERE passportnumber='$pno'"; $query = mysqli_query($conn, $sql); while($row = mysqli_fetch_assoc($query)) { ?> <div class="col-xs-6 col-sm-6 col-md-6 col-lg-5 text-right" id="review"> <ul> <li class="list">Passport Number </li> </ul> </div> <div id="review2"> <ul> <li class="list"><?php echo $row['passportnumber']; ?></li> </ul> </div> <br><br> <div class="col-xs-6 col-sm-12 col-md-12 col-lg-12" align="center" valign="top"> <a href="e-visa-application.php?actionType=edit" class="btn btn-primary btn-lg mgn-btm mgn-top ">Edit</a> <a href="process.php" class="btn btn-primary btn-lg mgn-btm mgn-top ">Continue to pay</a> </div> count变体来检索每行的当前t2值的行数,然后过滤到计数为1的行(即,t2的特定值仅出现一次。

SELECT t1, t2
FROM (SELECT t1, t2, count(*) OVER (PARTITION BY t2) t2_count
      FROM Demo) t
WHERE t2_count = 1;

此处,count(*) OVER (PARTITION BY t2)返回当前值为t2的行数。内部查询将返回

|--T1---------T2------T2_COUNT-|
| 100003 | 110000   | 2        |
| 100003 | 120000   | 2        |
| 100003 | 130000   | 1        | 
| 100003 | 140000   | 1        | 
| 100003 | 150000   | 1        | 
| 100004 | 110000   | 2        |
| 100004 | 120000   | 2        |
| 100004 | 160000   | 1        | 
| 100004 | 170000   | 1        | 
| 100004 | 180000   | 1        | 
|------------------------------| 

然后外部查询将过滤到您想要的结果集。