Oracle“Partition By”关键字

时间:2009-02-18 16:31:10

标签: sql oracle window-functions

有人可以解释一下partition by关键字的作用并给出一个简单的例子,以及为什么要使用它?我有一个由其他人编写的SQL查询,我正在试图找出它的作用。

分区的一个例子:

SELECT empno, deptno, COUNT(*) 
OVER (PARTITION BY deptno) DEPT_COUNT
FROM emp

我在网上看到的例子似乎有点过于深入。

6 个答案:

答案 0 :(得分:237)

PARTITION BY子句设置将在OVER子句中用于每个“GROUP”的记录范围。

在您的示例SQL中,DEPT_COUNT将返回该部门中每个员工记录的员工数。 (就像你对emp表进行去正规化一样;你仍然会返回emp表中的每条记录。)

emp_no  dept_no  DEPT_COUNT
1       10       3
2       10       3
3       10       3 <- three because there are three "dept_no = 10" records
4       20       2
5       20       2 <- two because there are two "dept_no = 20" records

如果有其他专栏(例如state),那么您可以计算该州有多少个部门。

就像获取GROUP BYSUMAVG等)的结果而没有结果集的聚合。

当您使用LAST OVERMIN OVER函数获取(例如)部门中的最低和最高工资,然后在计算中使用该工资时,它非常有用没有一个子选择,这要快得多。

阅读链接的AskTom article以获取更多详细信息。

答案 1 :(得分:126)

这个概念可以通过公认的答案得到很好的解释,但我发现越多的例子就会越好。它是一个增量的例子:

1) Boss说&#34;获取我们按品牌分组的库存数量&#34;

你说:&#34;没问题&#34;

SELECT 
      BRAND
      ,COUNT(ITEM_ID) 
FROM 
      ITEMS
GROUP BY 
      BRAND;

结果:

+--------------+---------------+
|  Brand       |   Count       | 
+--------------+---------------+
| H&M          |     50        |
+--------------+---------------+
| Hugo Boss    |     100       |
+--------------+---------------+
| No brand     |     22        |
+--------------+---------------+

2)老板说&#34;现在为我提供所有商品的清单,包括他们的品牌和相应品牌所拥有的商品数量&#34;

您可以尝试:

 SELECT 
      ITEM_NR
      ,BRAND
      ,COUNT(ITEM_ID) 
 FROM 
      ITEMS
 GROUP BY 
      BRAND;

但你得到:

ORA-00979: not a GROUP BY expression 

这是OVER (PARTITION BY BRAND)的来源:

 SELECT 
      ITEM_NR
      ,BRAND
      ,COUNT(ITEM_ID) OVER (PARTITION BY BRAND) 
 FROM 
      ITEMS;

这意味着:

  • COUNT(ITEM_ID) - 获取商品数量
  • OVER - 在行集上
  • (PARTITION BY BRAND) - 品牌相同

结果是:

+--------------+---------------+----------+
|  Items       |  Brand        | Count()  |
+--------------+---------------+----------+
|  Item 1      |  Hugo Boss    |   100    | 
+--------------+---------------+----------+
|  Item 2      |  Hugo Boss    |   100    | 
+--------------+---------------+----------+
|  Item 3      |  No brand     |   22     | 
+--------------+---------------+----------+
|  Item 4      |  No brand     |   22     | 
+--------------+---------------+----------+
|  Item 5      |  H&M          |   50     | 
+--------------+---------------+----------+

等...

答案 2 :(得分:26)

这是名为analytics的SQL扩展。 select语句中的“over”告诉oracle该函数是一个分析函数,而不是按函数分组。使用分析的优势在于,只需一次传递数据就可以收集总和,计数等等,而不是使用子选择或更糟糕的PL / SQL循环数据。

起初看起来确实令人困惑,但这很快就会成为第二天性。没有人比Tom Kyte更好地解释它。所以上面的链接很棒。

当然,阅读documentation是必须的。

答案 3 :(得分:10)

EMPNO     DEPTNO DEPT_COUNT

 7839         10          4
 5555         10          4
 7934         10          4
 7782         10          4 --- 4 records in table for dept 10
 7902         20          4
 7566         20          4
 7876         20          4
 7369         20          4 --- 4 records in table for dept 20
 7900         30          6
 7844         30          6
 7654         30          6
 7521         30          6
 7499         30          6
 7698         30          6 --- 6 records in table for dept 30

在这里,我们正在计算各自的deptno。 至于deptno 10,我们在表emp中有4条记录,对于deptno 20和30也有相似的结果。

答案 4 :(得分:2)

over partition关键字就像我们通过client_id对数据进行分区一样 创建每个客户端ID的子集

select client_id, operation_date,
       row_number() count(*) over (partition by client_id order by client_id ) as operationctrbyclient
from client_operations e
order by e.client_id;

此查询将返回client_id

完成的操作数

答案 5 :(得分:0)

我认为,该示例在分区如何工作以及分组方式如何方面存在细微差别。我的示例来自Oracle 12,如果我的示例恰好是编译错误。

我尝试过:

SELECT t.data_key
,      SUM ( CASE when t.state = 'A' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_a_rows
,      SUM ( CASE when t.state = 'B' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_b_rows
,      SUM ( CASE when t.state = 'C' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_c_rows
,      COUNT (1) total_rows
from mytable t
group by t.data_key  ---- This does not compile as the compiler feels that t.state isn't in the group by and doesn't recognize the aggregation I'm looking for

这可按预期进行:

SELECT distinct t.data_key
,      SUM ( CASE when t.state = 'A' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_a_rows
,      SUM ( CASE when t.state = 'B' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_b_rows
,      SUM ( CASE when t.state = 'C' THEN 1 ELSE 0 END) 
OVER   (PARTITION BY t.data_key) count_c_rows
,      COUNT (1) total_rows
from mytable t;

根据外部键“ data_key”产生每种状态下的元素数。因此,如果data_key ='APPLE'具有状态为'A'的3行,状态为'B'的2行,状态为'C'的行,则'APPLE'的对应行将为'APPLE',3、2 ,1、6。