有人可以解释一下partition by
关键字的作用并给出一个简单的例子,以及为什么要使用它?我有一个由其他人编写的SQL查询,我正在试图找出它的作用。
分区的一个例子:
SELECT empno, deptno, COUNT(*)
OVER (PARTITION BY deptno) DEPT_COUNT
FROM emp
我在网上看到的例子似乎有点过于深入。
答案 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 BY
(SUM
,AVG
等)的结果而没有结果集的聚合。
当您使用LAST OVER
或MIN 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。