【问题标题】:Order by in subquery and alias在子查询和别名中排序
【发布时间】:2019-09-25 08:11:31
【问题描述】:

我在 oracle 查询中的 order by 有问题。

select KEY, B, C, (select D from TABLE1 a where a.KEY = b.KEY and a.DATE< 
b.DATE order BY a.DATE and rownum =1 ) 
FROMSTATUS from TABLE2 b

我知道“order by”在子查询中不起作用。我将查询修改为:

select KEY, B, C, (select * from (select D from TABLE1 a where a.KEY = 
b.KEY and a.DATE< b.DATE order by DATE) where rownum = 1)
FROMSTATUS from TABLE2 b

但是通过这种方式 B.KEY 和 B.DATE 并没有被 oracle 解析

我只需要从 TABLE2 中选择一个 1 值,该值是前一个 a.DATE

例子:

 TABLE1
 KEY    DATE        A    B    C 
 1      01/31/2000  1    2    3
 2      02/25/2000  X    Y    Z   

 TABLE2
 KEY    DATE          D
 1      01/30/2000    1
 1      01/27/2000    2
 1      01/25/2000    2
 2      02/20/2000    4
 2      02/13/2000    1

我需要这个结果:

TABLE1.KEY   TABLE1.DATE    TABLE1.A TABLE1.B TABLE1.C TABLE2.DATE TABLE2.D
1            01/31/2000     1        2        3        01/30/2000  1
2            02/25/2000     X        Y        Z        02/20/2000  4

你能帮帮我吗?

(对不起我的英语不好)

【问题讨论】:

  • 跳过子查询,改为执行 LEFT JOIN。
  • 查询与您的描述不符。您已将 table1 和 table2 混合在一起。您还应用了错误的顺序,它必须是 order by date desc 才能首先获得最高日期。
  • @ThorstenKettner 你有理由,我有正确的问题

标签: sql oracle subquery


【解决方案1】:

union 之后的row_number() 会得到你的输出。

 select tFinal.DATE, tFinal.KEY 
 from (select row_number() over (partition by KEY order by t1.T, t1.DATE desc) as rn, t1.DATE, t1.KEY 
        from 
        (select DATE, KEY, 't1' as T from TABLE1
        union all
        select DATE, KEY, 't2' as T from TABLE2) t1) tFinal
 Where rn = 2

【讨论】:

    【解决方案2】:

    您可以为此使用窗口函数:

    WITH cte AS (
        SELECT TABLE2.KEY, TABLE2.B, TABLE2.C, TABLE1.D
             , ROW_NUMBER() OVER (PARTITION BY TABLE2.KEY, TABLE2.DATE ORDER BY TABLE1.DATE DESC) AS rn
        FROM TABLE2
        LEFT JOIN TABLE1 ON TABLE2.KEY = TABLE1.KEY AND TABLE2.DATE > TABLE1.DATE
    )
    SELECT *
    FROM cte
    WHERE rn = 1
    

    【讨论】:

      【解决方案3】:

      这是一个使用聚合的答案:

      WITH t1 AS (SELECT 1 KEY, to_date('31/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
                  SELECT 2 KEY, to_date('25/02/2000', 'dd/mm/yyyy') dt FROM dual),
           t2 AS (SELECT 1 KEY, to_date('30/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
                  SELECT 1 KEY, to_date('27/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
                  SELECT 1 KEY, to_date('25/01/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
                  SELECT 2 KEY, to_date('20/02/2000', 'dd/mm/yyyy') dt FROM dual UNION ALL
                  SELECT 2 KEY, to_date('13/02/2000', 'dd/mm/yyyy') dt FROM dual)
      SELECT t1.KEY,
             t1.dt t1_date,
             MAX(t2.dt) t2_date
      FROM   t1
             LEFT OUTER JOIN t2 ON t1.key = t2.key AND t2.dt < t1.dt
      GROUP BY t1.key, t1.dt
      ORDER BY t1.key;
      
             KEY T1_DATE     T2_DATE
      ---------- ----------- -----------
               1 31/01/2000  30/01/2000
               2 25/02/2000  20/02/2000
      

      我在这里假设 t1.key 是一个唯一的列。这是否比您的数据的任何其他答案更具性能取决于您来测试 *{:-)

      【讨论】:

        【解决方案4】:

        在 Oracle 中,您可以为此使用 KEEP LAST

        select
          key,
          b,
          c,
          (
            select max(d) keep (dense_rank last order by t2.date)
            from table2 t2
            where t2.key = t1.key and t2.date < t1.date
          ) as fromstatus
        from table1 t1;
        

        从 Oracle 12c 开始,您还可以使用 FETCH FIRST ROW

        select
          key,
          b,
          c,
          (
            select d
            from table2 t2
            where t2.key = t1.key and t2.date < t1.date
            order by t2.date desc
            fetch first row only
          ) as fromstatus
        from table1 t1;
        

        或者,将子查询移动到FROM 子句:

        select
          t1.key,
          t1.b,
          t1.c,
          first_t2.d as fromstatus
        from table1 t1
        outer apply
        (
          select d
          from table2 t2
          where t2.key = t1.key and t2.date < t1.date
          order by t2.date desc
          fetch first row only
        ) first_t2;
        

        最后一个查询的优点是您可以轻松地从 table2 行中选择更多值,而不仅仅是一个。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2019-03-09
          相关资源
          最近更新 更多