1

我正在学习 oracle SQL,我有一个如下表:

+--------+--------+------------------------+
| name   | nation | count                  |
+--------+--------+------------------------+
| Ruben  | UK     | 2                      |
| Ruben  | EEUU   | 16                     |
| Cesar  | UK     | 21                     |
| Cesar  | EEUU   | 12                     |
| Cesar  | FRANCE | 4                      |
| John   | FRANCE | 3                      |
| John   | UK     | 7                      |
| ....   | ..     | ..                     |
+--------+--------+------------------------+

上表表示我使用查询创建的内联视图。如您所见,表格按名称和国家分组并进行计数。我想使用 count 列过滤表以获得如下内容:

+--------+--------+
| name   | nation |
+--------+--------+
| Ruben  | EEUU   |
| Cesar  | UK     |
| John   | UK     |
| ....   | ..     |
+--------+--------+  

如您所见,对于每个名称,我想根据计数选择国家。

4

2 回答 2

3

您可以使用另一个级别的内部查询来执行此操作。就像是:

select name, nation
from (
  select name, nation, cnt,
    row_number() over (partition by name, nation order by cnt desc) as rn
  from (
    select name, nation, count(*) as cnt
    from <your table>
  )
)
where rn = 1;

row_number()分析将一个伪列添加到最里面的查询,为每个名称/国家将计数最高的行排名为 1;然后,最外层的查询只查看那些排名第一的查询。

您需要决定如何处理关系 - 如果两个国家/名称行具有相同的计数,您可以使用rank()而不是显示两者row_number()order by或者您可以通过在子句中添加另一列来决定选择哪一个。目前,如果有两个相同的,它只会显示其中一个 - 它显示的是相当随意的。

于 2014-03-05T15:01:39.233 回答
3

使用keep分析关键字:

select name, min(nation) keep (dense_rank last order by cnt)
from (select name, nation, count(*) as cnt
      from /* your data source */
      group by name, nation)
group by name
  1. min(nation)- min 在这种情况下是没有意义的,但你必须保留它(没有它就不行)
  2. keep- 只保留一个结果nation
  3. dense_rank last说拿起最后一个元素
  4. order by cnt说如何定义元素的顺序

最终,它将使每个名字都成为人数最多的国家。可以达到相同的结果

select name, min(nation) keep (dense_rank first order by cnt desc)
于 2014-03-05T16:43:37.880 回答