【问题标题】:Advanced SQL Query - Universal Temporary Table or Something Else?高级 SQL 查询 - 通用临时表还是其他?
【发布时间】:2015-11-06 14:02:39
【问题描述】:

我对 Oracle SQL 查询还很陌生,遇到了一个我无法解决的问题,也无法通过 Google/StackOverflow 的搜索栏很好地描述以找到答案。

我有两张桌子。

为简单起见,假设表 A 有两个变量,这两个变量在表中都不是唯一的。

|订购 |特点| |1 |一个| |1 |乙| |1 | C| |2 |乙| |2 | C| |3 |一个| |3 | C| |4 |一个| |4 |乙|

表 B 包含 Order 变量和一个日期变量。在这种情况下,Order 变量是唯一的。

|订购 |日期| |1 | 8月1日| |2 | 8月1日| |3 | 8月1日| |4 |7 月 31 日|

这是棘手的部分(对我而言)。我想要表 A,但没有任何命令:

  1. 不包含功能“A”的实例
  2. 表 B 中 8 月份以内

看起来像:

|订购 |特点| |1 |一个| |1 |乙| |1 | C| |3 |一个| |3 | C|

我试图让它与全局本地表一起使用,但没有成功。在该策略中,我首先将所有带有“A”的订单拉到一个表中,然后在临时表中拉出所有带有订单的功能,并且日期在八月。

另外,我认为没有临时表有一种更有效的方法,但我的经验有限。

有什么想法吗?

【问题讨论】:

    标签: sql oracle global temporary


    【解决方案1】:

    有几种方法可以实现这一点(使用 GROUP BY、IN、EXISTS、ANY 加入),其中都不需要临时表或类似技术。

    我选择加入是因为它很容易理解。

    Select order, feature 
    From tableA a
    WHERE a.Order  in (select order from TableA where Feature = 'A' )
    and a.order in (select order from tableB where be extract(month from date) = 8  )
    

    【讨论】:

    • 无论如何你都不需要and order is not null。您将 IN 与 NOT IN 混淆了,其中 null 确实可能是一个问题。
    • 我认为month(date)在Oracle中应该是extract(month from date)
    • @ThorstenKettner doh 是的,不知道我在想什么
    【解决方案2】:

    我认为您必须执行子查询以在您的条件中查找顺序,然后选择您想要的信息。

    试试这个:

    SELECT a.order, a.feature
    FROM tableA a
    INNER JOIN (SELECT DISTINCT a1.order
                FROM tableA a1 
                INNER JOIN tableB b 
                     ON b.order = a1.order
                WHERE month(b.date) = 8
                     AND a1.feature = 'A'
               ) c on c.order = a.order;
    

    【讨论】:

      【解决方案3】:

      我会通过使用分析函数来测试是否存在“A”特征,然后加入另一个表以获取 dt。

      正如你的问题所写,我认为这就是你所追求的:

      with table_a as (select 1 ord, 'A' feature from dual union all
                       select 1 ord, 'B' feature from dual union all
                       select 1 ord, 'C' feature from dual union all
                       select 2 ord, 'B' feature from dual union all
                       select 2 ord, 'C' feature from dual union all
                       select 3 ord, 'A' feature from dual union all
                       select 3 ord, 'C' feature from dual union all
                       select 4 ord, 'A' feature from dual union all
                       select 4 ord, 'B' feature from dual),
           table_b as (select 1 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all
                       select 2 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all
                       select 3 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all
                       select 4 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual union all
                       select 5 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual),
               res as (select ta.ord,
                              ta.feature,
                              max(case when ta.feature = 'A' then 'A' end) over (partition by ta.ord) a_present,
                              tb.dt
                       from   table_a ta
                              inner join table_b tb on (ta.ord = tb.ord))
      select ord,
             feature
      from   res
      where  a_present is not null
      and    to_char(dt, 'mm') != '08';
      
             ORD FEATURE
      ---------- -------
               4 A      
               4 B
      

      但是,您指出的结果表明,您实际上想要在每个组中都包含“A”并且确实落在 8 月份的结果

      with table_a as (select 1 ord, 'A' feature from dual union all
                       select 1 ord, 'B' feature from dual union all
                       select 1 ord, 'C' feature from dual union all
                       select 2 ord, 'B' feature from dual union all
                       select 2 ord, 'C' feature from dual union all
                       select 3 ord, 'A' feature from dual union all
                       select 3 ord, 'C' feature from dual union all
                       select 4 ord, 'A' feature from dual union all
                       select 4 ord, 'B' feature from dual),
           table_b as (select 1 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all
                       select 2 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all
                       select 3 ord, to_date('01/08/2015', 'dd/mm/yyyy') dt from dual union all
                       select 4 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual union all
                       select 5 ord, to_date('31/07/2015', 'dd/mm/yyyy') dt from dual),
               res as (select ta.ord,
                              ta.feature,
                              max(case when ta.feature = 'A' then 'A' end) over (partition by ta.ord) a_present,
                              tb.dt
                       from   table_a ta
                              inner join table_b tb on (ta.ord = tb.ord))
      select ord,
             feature
      from   res
      where  a_present is not null
      and    to_char(dt, 'mm') = '08';
      
             ORD FEATURE
      ---------- -------
               1 A      
               1 B      
               1 C      
               3 A      
               3 C  
      

      【讨论】:

        【解决方案4】:

        如果您对分析函数和子查询不满意(您应该会,但您的问题表明您可能不会),您可以使用直接连接来做到这一点 - 没什么特别的:

        SELECT a2.ord, a2.feature
        FROM table_a a1 
        inner join table_b b on b.ord = a1.ord 
        inner join table_a a2 on a2.ord = a1.ord 
        where b.dt between to_date('01-AUG-2015') and last_day(to_date('01-AUG-2015') + (86399/86400))
         and a1.feature = 'A';
        

        基本上,您首先去表 A 只获取具有特征 A 的行,然后再去表 A 以获取这些订单的所有行。

        您的帖子没有说明一个订单是否可以两次具有相同的功能。我假设不是,但如果是,那么您将需要选择 DISTINCT 而不是 SELECT。

        就个人而言,我可能会使用上面描述的分析函数来写这个。我添加这个替代方案只是因为它只使用非常基本的 SQL。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-06-12
          • 2021-02-11
          相关资源
          最近更新 更多