如何从另一个表中查找缺失值

时间:2016-10-20 10:22:05

标签: sql database oracle

想象一下,如果我有两张这样的表:

Table Name: user
| id | user_id | password |

Table Name: permissions
| id | admin | write | delete | transfer |

用这个填充表格:

Inserting into user table:
    - 0, joshsh, asdf01
    - 1, jakesh, asdf02
    - 2, annsh, asdf03
    - 3, lamsh, asdf04

Inserting into permissions table:
    - 0, yes, yes, yes, yes
    - 1, yes, yes, yes, yes
    - 2, no, yes, yes, yes

我没有将第4个值添加到permissions表中。我如何查询语句以找到我忘记的数字(如果它是一个大数据库)?

4 个答案:

答案 0 :(得分:2)

假设id列是基于id列的权限和用户表之间的连接(并且该id是两个表中的主要/唯一键),这里有几个解决方案:

select id from permissions
minus
select id from user;

select * from user
where id not in (select id from permissions);

答案 1 :(得分:2)

有很多方法可以获得相同的结果,这有两种可能的方式:

使用NOT EXISTS:

SQL> select u.*
  2  from user_ u
  3  where not exists (
  4                      select 1
  5                      from permissions p
  6                      where u.id = p.id
  7                   );

        ID USER_ID    PASSWORD
---------- ---------- ----------
         3 lamsh      asdf04


Execution Plan
----------------------------------------------------------
Plan hash value: 3342498783

----------------------------------------------------------------------------------
| Id  | Operation          | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |             |     4 |   160 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI    |             |     4 |   160 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| USER_       |     4 |   108 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| PERMISSIONS |     3 |    39 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("U"."ID"="P"."ID")

Note
-----
   - dynamic sampling used for this statement (level=2)

使用外部联接:

SQL> select u.*
  2  from user_ u
  3       left outer join permissions p
  4         on (u.id = p.id)
  5  where p.id is null;

        ID USER_ID    PASSWORD
---------- ---------- ----------
         3 lamsh      asdf04


Execution Plan
----------------------------------------------------------
Plan hash value: 3342498783

----------------------------------------------------------------------------------
| Id  | Operation          | Name        | Rows  | Bytes | Cost (%CPU)| Time     |
----------------------------------------------------------------------------------
|   0 | SELECT STATEMENT   |             |     4 |   160 |     7  (15)| 00:00:01 |
|*  1 |  HASH JOIN ANTI    |             |     4 |   160 |     7  (15)| 00:00:01 |
|   2 |   TABLE ACCESS FULL| USER_       |     4 |   108 |     3   (0)| 00:00:01 |
|   3 |   TABLE ACCESS FULL| PERMISSIONS |     3 |    39 |     3   (0)| 00:00:01 |
----------------------------------------------------------------------------------

Predicate Information (identified by operation id):
---------------------------------------------------

   1 - access("U"."ID"="P"."ID")

Note
-----
   - dynamic sampling used for this statement (level=2)

请注意,Oracle对两个语句执行了相同的解释计划,考虑到测试是使用两个非常小的表而没有索引而没有统计信息。 另外,考虑到有很多方法可以获得相同的结果;性能很大程度上取决于您的数据,统计数据,索引......

ps我使用USER_代替USER,以避免出现问题。

答案 2 :(得分:0)

如果两个表不相等,则对两个表应用count(*),然后生成alert,并且可以使用sql server agent job生成alter。 或者你可以做到这一点 从用户中选择*作为u  完全外部联接权限为p 在a.id中(从用户中选择id)

答案 3 :(得分:0)

最好的方法是在where子句中使用LEFT JOIN和IS NULL,它在每个方面都优雅高效:

SELECT u.*
FROM user u 
LEFT JOIN permissions p ON u.id = p.id
WHERE p.id IS NULL