窗口函数问题 - 最大分区

时间:2014-06-03 09:23:06

标签: sql oracle window-functions

我尝试使用外连接和max / count / ... over partition将这些SQL语句(包含许多子查询)重写为更高效的形式。旧陈述:

select a.ID,
     (select max(b.valA) from something b where a.ID = b.ID_T and b.status != 0),
     (select max(b.valB) from something b where a.ID = b.ID_T and b.status != 0),
     (select max(b.valC) from something b where a.ID = b.ID_T and b.status != 0),
     (select max(b.valD) from something b where a.ID = b.ID_T)
from tool a;

这里重要的是 - max(b.valD)有不同的条件。首先,我没有注意到这种差异并写下这样的东西:

select distinct a.ID,
      max(b.valA) over (partition by b.ID_T),
      max(b.valB) over (partition by b.ID_T),
      max(b.valC) over (partition by b.ID_T),
      max(b.valD) over (partition by b.ID_T),
from tool a, 
     (select * from something
     where status != 0) b
where a.ID = b.ID_T(+);

我可以在 b.status!= 0 b.status!= 0 中使用 max over partition 的某个地方吗?或者我应该更好地添加第3个表来加入:

select distinct a.ID,
      max(b.valA) over (partition by b.ID_T),
      max(b.valB) over (partition by b.ID_T),
      max(b.valC) over (partition by b.ID_T),
      max(c.valD) over (partition by c.ID_T),
from tool a, 
     (select * from something 
      where status != 0) b, 
     something c
where a.ID = b.ID_T(+)
     and a.ID = c.ID_T(+);

问题在于选择和加入数百万行,我的例子就是简化我的查询。谁能帮助我实现更高效的sql?

2 个答案:

答案 0 :(得分:1)

您可以尝试使用CASE执行此操作:

select a.ID,
       max(CASE WHEN b.status=0 THEN b.valA END),
       max(CASE WHEN b.status=0 THEN b.valB END),
       max(CASE WHEN b.status=0 THEN b.valC END),
       max(b.valD)
  from tool a
  left join something b ON( b.ID_T = a.ID )
  group by a.ID;

请注意,我使用“new”join-syntax替换了隐式连接,以提高可读性。

答案 1 :(得分:0)

另一种方法是使用JOIN和子查询分组:

select a.ID,
     b.MAX_A,
     b.MAX_B,
     b.MAX_C,
     b2.MAX_D 
from tool a
LEFT JOIN
 (
    SELECT ID_T,max(valA) MAX_A, max(valB) MAX_B, max(valC) MAX_C
    FROM something 
    WHERE status != 0
    GROUP BY ID_T     
  ) b
  ON a.ID=b.ID_T
LEFT JOIN
 (
    SELECT ID_T, max(valD) MAX_D
    FROM something 
    GROUP BY ID_T     
  ) b2
  ON a.ID=b2.ID_T