sql - 如何将子查询where条件移出子查询?

标签 sql oracle join subquery outer-join

在 Oracle 中,我有一个相当大的 select 语句。我想将其保存为 View ,以便我可以从 .NET 程序调用它并将其用作我们必须生成的一些统计数据的基础。使用 View 时,它始终按日期进行过滤。

我想要这样的东西:

select * from my_view
where my_view.date = '2014-01-01';

问题是我需要在子查询的where条件中使用日期作为参数:

select * from table1
left outer join (
    select * from table2
    where table2.date = :somedate)
  on table1.Id = table2.Id;

...无法将其制作为 View 。

有没有办法可以将日期比较移到子查询之外,而不会弄乱左外连接?

不该做什么:

这会创建一个内部联接 - 这不是我想要的:

select * from table1
left outer join 
  table2
  on table1.Id = table2.Id
where table2.date = '2014-01-01';

此选择过滤掉 table1 中的行,这些行不在指定日期连接到行,但在另一个日期连接到行:

select * from table1
left outer join 
  table2
  on table1.Id = table2.Id
where table2.Id is null
   or table2.date = '2014-01-01';

最佳答案

有多种方法可以参数化 View - 例如使用包或应用程序上下文(您可以使用内置上下文 CLIENTCONTEXT)。但所有这些方式都需要对参数的完全控制,并且您必须使用附加功能来设置参数值,这可能是一个严重的缺点:

SQL> create or replace view param_view
  2  as
  3  select d.name, e.firstname, e.lastname, e.email
  4  from department d left join employee e
  5  on (d.id = e.departmentid
  6  and e.firstname = sys_context('CLIENTCONTEXT','EMPNAME'))
  7  /

View created.

SQL> exec dbms_session.set_context('CLIENTCONTEXT','EMPNAME','Scott')

PL/SQL procedure completed

SQL> select * from param_view;

NAME                 FIRSTNAME  LASTNAME             EMAIL                      
-------------------- ---------- -------------------- --------------------       
Department A         Scott      Tiger                <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="cfb7b7b78fa8a2aea6a3e1aca0a2" rel="noreferrer noopener nofollow">[email protected]</a>              
Department B                                                                    
Department C                                                                    

SQL> exec dbms_session.set_context('CLIENTCONTEXT','EMPNAME','Allen')

PL/SQL procedure completed

SQL> select * from param_view;

NAME                 FIRSTNAME  LASTNAME             EMAIL                      
-------------------- ---------- -------------------- --------------------       
Department A         Allen      Dirk                 <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="daa3a3a39abdb7bbb3b6f4b9b5b7" rel="noreferrer noopener nofollow">[email protected]</a>              
Department B                                                                    
Department C   

SQL> create or replace package pck_test
  2  is
  3   function get return varchar2;
  4   procedure set (x in varchar2);
  5  end;
  6  /

Package created.

SQL> create or replace package body pck_test
  2  is
  3   name employee.firstname%type;
  4  
  5   function get return varchar2
  6   is
  7   begin
  8     return name;
  9   end;
 10  
 11   procedure set (x in varchar2)
 12   is
 13   begin
 14     name := x;
 15   end;
 16  
 17  end;
 18  /

Package body created.

SQL> create or replace view param_view
  2  as
  3  select d.name, e.firstname, e.lastname, e.email
  4  from department d left join employee e
  5  on (d.id = e.departmentid
  6  and e.firstname = pck_test.get)
  7  /

View created

SQL> exec pck_test.set('Scott')

PL/SQL procedure completed.

SQL> select * from param_view;

NAME                 FIRSTNAME  LASTNAME             EMAIL                      
-------------------- ---------- -------------------- --------------------       
Department A         Scott      Tiger                <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="bec6c6c6fed9d3dfd7d290ddd1d3" rel="noreferrer noopener nofollow">[email protected]</a>              
Department B                                                                    
Department C                                                                    

SQL> exec pck_test.set('Allen')

PL/SQL procedure completed.

SQL> select * from param_view;

NAME                 FIRSTNAME  LASTNAME             EMAIL                      
-------------------- ---------- -------------------- --------------------       
Department A         Allen      Dirk                 <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="027b7b7b42656f636b6e2c616d6f" rel="noreferrer noopener nofollow">[email protected]</a>              
Department B                                                                    
Department C                                                                    

SQL> select d.name, e.firstname, e.lastname, e.email
  2  from department d left join employee e
  3  on (d.id = e.departmentid)
  4  /

NAME                 FIRSTNAME  LASTNAME             EMAIL                      
-------------------- ---------- -------------------- --------------------       
Department A         Allen      Dirk                 <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="97eeeeeed7f0faf6fefbb9f4f8fa" rel="noreferrer noopener nofollow">[email protected]</a>              
Department A         Scott      Tiger                <a href="https://stackoverflow.com/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="5d2525251d3a303c3431733e3230" rel="noreferrer noopener nofollow">[email protected]</a>              
Department B                                                                    
Department C  

关于sql - 如何将子查询where条件移出子查询?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23366026/

相关文章:

sql - 在 SQL Azure 中使用 sys.fn_IsBitSetInBitmask

sql - 当列的值与上一行相比发生变化时选择行

oracle - 如何在 Oracle 中授权用户/应用程序组合?

sql - 子查询返回不正确的值

java - XPath 歧义

mysql - SQL查询连接多个具有一对多关系的表

mysql - 使用嵌套查询和内连接清理 SQL 查询

php - 如何计算属于另一列中不同值的列中的所有相同值

sql - MySql 使用 Sum 连接

mysql - 选择表 A 中的所有记录,即使其中一个或多个 ID(即 FK)不存在于表 B 中